xref: /AOO41X/main/sw/source/core/undo/untblk.cxx (revision 69a743679e823ad8f875be547552acb607b8ada5)
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 <hintids.hxx>
28 #include <fmtanchr.hxx>
29 #include <frmfmt.hxx>
30 #include <doc.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IShellCursorSupplier.hxx>
33 #include <docary.hxx>
34 #include <swundo.hxx>           // fuer die UndoIds
35 #include <pam.hxx>
36 #include <ndtxt.hxx>
37 #include <UndoCore.hxx>
38 #include <rolbck.hxx>
39 #include <redline.hxx>
40 
41 
42 
SwUndoInserts(SwUndoId nUndoId,const SwPaM & rPam)43 SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam )
44     : SwUndo( nUndoId ), SwUndRng( rPam ),
45     pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ),
46     bSttWasTxtNd( sal_True ), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
47 {
48     pHistory = new SwHistory;
49     SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
50 
51     SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
52     if( pTxtNd )
53     {
54         pTxtFmtColl = pTxtNd->GetTxtColl();
55         pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
56                             0, pTxtNd->GetTxt().Len(), false );
57         if( pTxtNd->HasSwAttrSet() )
58             pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
59 
60         if( !nSttCntnt )    // dann werden Flys mitgenommen !!
61         {
62             sal_uInt16 nArrLen = pDoc->GetSpzFrmFmts()->Count();
63             for( sal_uInt16 n = 0; n < nArrLen; ++n )
64             {
65                 SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
66                 SwFmtAnchor const*const  pAnchor = &pFmt->GetAnchor();
67                 const SwPosition* pAPos = pAnchor->GetCntntAnchor();
68                 if (pAPos &&
69                     (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
70                      nSttNode == pAPos->nNode.GetIndex() )
71                 {
72                     if( !pFrmFmts )
73                         pFrmFmts = new SvPtrarr;
74                     pFrmFmts->Insert( pFmt, pFrmFmts->Count() );
75                 }
76             }
77         }
78     }
79     // Redline beachten
80     if( pDoc->IsRedlineOn() )
81     {
82         pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
83         SetRedlineMode( pDoc->GetRedlineMode() );
84     }
85 }
86 
87 // setze den Destination-Bereich nach dem Einlesen.
88 
SetInsertRange(const SwPaM & rPam,sal_Bool bScanFlys,sal_Bool bSttIsTxtNd)89 void SwUndoInserts::SetInsertRange( const SwPaM& rPam, sal_Bool bScanFlys,
90                                     sal_Bool bSttIsTxtNd )
91 {
92     const SwPosition* pTmpPos = rPam.End();
93     nEndNode = pTmpPos->nNode.GetIndex();
94     nEndCntnt = pTmpPos->nContent.GetIndex();
95     if( rPam.HasMark() )
96     {
97         if( pTmpPos == rPam.GetPoint() )
98             pTmpPos = rPam.GetMark();
99         else
100             pTmpPos = rPam.GetPoint();
101 
102         nSttNode = pTmpPos->nNode.GetIndex();
103         nSttCntnt = pTmpPos->nContent.GetIndex();
104 
105         if( !bSttIsTxtNd )      // wird eine Tabellenselektion eingefuegt,
106         {
107             ++nSttNode;         // dann stimmt der CopyPam nicht ganz
108             bSttWasTxtNd = sal_False;
109         }
110     }
111 
112     if( bScanFlys && !nSttCntnt )
113     {
114         // dann alle neuen Flys zusammen sammeln !!
115         SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
116         sal_uInt16 nFndPos, nArrLen = pDoc->GetSpzFrmFmts()->Count();
117         for( sal_uInt16 n = 0; n < nArrLen; ++n )
118         {
119             SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
120             SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
121             SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
122             if (pAPos &&
123                 (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
124                 nSttNode == pAPos->nNode.GetIndex() )
125             {
126                 if( !pFrmFmts ||
127                     USHRT_MAX == ( nFndPos = pFrmFmts->GetPos( pFmt ) ) )
128                 {
129                     ::boost::shared_ptr<SwUndoInsLayFmt> const pFlyUndo(
130                         new SwUndoInsLayFmt(pFmt, 0, 0));
131                     m_FlyUndos.push_back(pFlyUndo);
132                 }
133                 else
134                     pFrmFmts->Remove( nFndPos );
135             }
136         }
137         delete pFrmFmts, pFrmFmts = 0;
138     }
139 }
140 
141 
~SwUndoInserts()142 SwUndoInserts::~SwUndoInserts()
143 {
144     if( pPos )      // loesche noch den Bereich aus dem UndoNodes Array
145     {
146         // Insert speichert den Inhalt in der IconSection
147         SwNodes& rUNds = pPos->nNode.GetNodes();
148         if( pPos->nContent.GetIndex() )         // nicht den gesamten Node loeschen
149         {
150             SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
151             ASSERT( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
152             if( pTxtNd ) // Robust
153             {
154                 pTxtNd->EraseText( pPos->nContent );
155             }
156             pPos->nNode++;
157         }
158         pPos->nContent.Assign( 0, 0 );
159         rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
160                                     pPos->nNode.GetIndex() );
161         delete pPos;
162     }
163     delete pFrmFmts;
164     delete pRedlData;
165 }
166 
167 
UndoImpl(::sw::UndoRedoContext & rContext)168 void SwUndoInserts::UndoImpl(::sw::UndoRedoContext & rContext)
169 {
170     SwDoc *const pDoc = & rContext.GetDoc();
171     SwPaM *const pPam = & AddUndoRedoPaM(rContext);
172 
173     if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
174         pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
175 
176     // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
177     // JoinNext ausgefuehrt werden.
178     sal_Bool bJoinNext = nSttNode != nEndNode &&
179                 pPam->GetMark()->nNode.GetNode().GetTxtNode() &&
180                 pPam->GetPoint()->nNode.GetNode().GetTxtNode();
181 
182 
183     // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
184     if( nSttNode != nEndNode || nSttCntnt != nEndCntnt )
185     {
186         if( nSttNode != nEndNode )
187         {
188             SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
189             if( pTxtNd && pTxtNd->GetTxt().Len() == nEndCntnt )
190                 pLastNdColl = pTxtNd->GetTxtColl();
191         }
192 
193         RemoveIdxFromRange( *pPam, sal_False );
194         SetPaM(*pPam);
195 
196         // sind Fussnoten oder CntntFlyFrames im Text ??
197         nSetPos = pHistory->Count();
198         nNdDiff = pPam->GetMark()->nNode.GetIndex();
199         DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() );
200         nNdDiff -= pPam->GetMark()->nNode.GetIndex();
201 
202         if( *pPam->GetPoint() != *pPam->GetMark() )
203         {
204             pPos = new SwPosition( *pPam->GetPoint() );
205             MoveToUndoNds( *pPam, &pPos->nNode, &pPos->nContent );
206 
207             if( !bSttWasTxtNd )
208                 pPam->Move( fnMoveBackward, fnGoCntnt );
209         }
210     }
211 
212     if (m_FlyUndos.size())
213     {
214         sal_uLong nTmp = pPam->GetPoint()->nNode.GetIndex();
215         for (size_t n = m_FlyUndos.size(); 0 < n; --n)
216         {
217             m_FlyUndos[ n-1 ]->UndoImpl(rContext);
218         }
219         nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex();
220     }
221 
222     SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
223     SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode();
224     if( pTxtNode )
225     {
226         if( !pTxtFmtColl )      // falls 0, dann war hier auch kein TextNode,
227         {                       // dann muss dieser geloescht werden,
228             SwNodeIndex aDelIdx( rIdx );
229             rIdx++;
230             SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
231             xub_StrLen nCnt = 0; if( pCNd ) nCnt = pCNd->Len();
232             pPam->GetPoint()->nContent.Assign( pCNd, nCnt );
233             pPam->SetMark();
234             pPam->DeleteMark();
235 
236             RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() );
237 
238             pDoc->GetNodes().Delete( aDelIdx, 1 );
239         }
240         else
241         {
242             if( bJoinNext && pTxtNode->CanJoinNext())
243             {
244                 {
245                     RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx,
246                         SwIndex( pTxtNode, pTxtNode->GetTxt().Len() )));
247                 }
248                 pTxtNode->JoinNext();
249             }
250             // reset all text attributes in the paragraph!
251             pTxtNode->RstTxtAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(), 0, 0, true );
252 
253             // setze alle Attribute im Node zurueck
254             pTxtNode->ResetAllAttr();
255 
256             if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
257                 pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
258 
259             pHistory->SetTmpEnd( nSetPos );
260             pHistory->TmpRollback( pDoc, 0, false );
261         }
262     }
263 }
264 
RedoImpl(::sw::UndoRedoContext & rContext)265 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
266 {
267     // setze noch den Cursor auf den Redo-Bereich
268     SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
269     SwDoc* pDoc = pPam->GetDoc();
270     pPam->DeleteMark();
271     pPam->GetPoint()->nNode = nSttNode - nNdDiff;
272     SwCntntNode* pCNd = pPam->GetCntntNode();
273     pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
274 
275     SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
276     if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
277         pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
278 
279     pHistory->SetTmpEnd( nSetPos );
280 
281     // alte Anfangs-Position fuers Rollback zurueckholen
282     if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
283     {
284         sal_Bool bMvBkwrd = MovePtBackward( *pPam );
285 
286         // Inhalt wieder einfuegen. (erst pPos abmelden !!)
287         sal_uLong nMvNd = pPos->nNode.GetIndex();
288         xub_StrLen nMvCnt = pPos->nContent.GetIndex();
289         DELETEZ( pPos );
290         MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
291         if( bSttWasTxtNd )
292             MovePtForward( *pPam, bMvBkwrd );
293         pPam->Exchange();
294     }
295 
296     if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
297     {
298         SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
299         if( pTxtNd )
300             pTxtNd->ChgFmtColl( pTxtFmtColl );
301     }
302     pTxtFmtColl = pSavTxtFmtColl;
303 
304     if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
305         pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
306     {
307         SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
308         if( pTxtNd )
309             pTxtNd->ChgFmtColl( pLastNdColl );
310     }
311 
312     for (size_t n = m_FlyUndos.size(); 0 < n; --n)
313     {
314         m_FlyUndos[ n-1 ]->RedoImpl(rContext);
315     }
316 
317     pHistory->Rollback( pDoc, nSetPos );
318 
319     if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
320     {
321         RedlineMode_t eOld = pDoc->GetRedlineMode();
322         pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
323         pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
324         pDoc->SetRedlineMode_intern( eOld );
325     }
326     else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
327             pDoc->GetRedlineTbl().Count() )
328         pDoc->SplitRedline( *pPam );
329 }
330 
RepeatImpl(::sw::RepeatContext & rContext)331 void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext)
332 {
333     SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() );
334     SetPaM( aPam );
335     SwPaM & rRepeatPaM( rContext.GetRepeatPaM() );
336     aPam.GetDoc()->CopyRange( aPam, *rRepeatPaM.GetPoint(), false );
337 }
338 
339 
340 //////////////////////////////////////////////////////////////////////////
341 
SwUndoInsDoc(const SwPaM & rPam)342 SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
343     : SwUndoInserts( UNDO_INSDOKUMENT, rPam )
344 {
345 }
346 
SwUndoCpyDoc(const SwPaM & rPam)347 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
348     : SwUndoInserts( UNDO_COPY, rPam )
349 {
350 }
351 
352