xref: /AOO41X/main/sw/source/core/undo/untblk.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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 
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 
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 
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 
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->RstAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(),
252                                 0, 0, true );
253 
254             // setze alle Attribute im Node zurueck
255             pTxtNode->ResetAllAttr();
256 
257             if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
258                 pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
259 
260             pHistory->SetTmpEnd( nSetPos );
261             pHistory->TmpRollback( pDoc, 0, false );
262         }
263     }
264 }
265 
266 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
267 {
268     // setze noch den Cursor auf den Redo-Bereich
269     SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
270     SwDoc* pDoc = pPam->GetDoc();
271     pPam->DeleteMark();
272     pPam->GetPoint()->nNode = nSttNode - nNdDiff;
273     SwCntntNode* pCNd = pPam->GetCntntNode();
274     pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
275 
276     SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
277     if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
278         pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
279 
280     pHistory->SetTmpEnd( nSetPos );
281 
282     // alte Anfangs-Position fuers Rollback zurueckholen
283     if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
284     {
285         sal_Bool bMvBkwrd = MovePtBackward( *pPam );
286 
287         // Inhalt wieder einfuegen. (erst pPos abmelden !!)
288         sal_uLong nMvNd = pPos->nNode.GetIndex();
289         xub_StrLen nMvCnt = pPos->nContent.GetIndex();
290         DELETEZ( pPos );
291         MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
292         if( bSttWasTxtNd )
293             MovePtForward( *pPam, bMvBkwrd );
294         pPam->Exchange();
295     }
296 
297     if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
298     {
299         SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
300         if( pTxtNd )
301             pTxtNd->ChgFmtColl( pTxtFmtColl );
302     }
303     pTxtFmtColl = pSavTxtFmtColl;
304 
305     if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
306         pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
307     {
308         SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
309         if( pTxtNd )
310             pTxtNd->ChgFmtColl( pLastNdColl );
311     }
312 
313     for (size_t n = m_FlyUndos.size(); 0 < n; --n)
314     {
315         m_FlyUndos[ n-1 ]->RedoImpl(rContext);
316     }
317 
318     pHistory->Rollback( pDoc, nSetPos );
319 
320     if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
321     {
322         RedlineMode_t eOld = pDoc->GetRedlineMode();
323         pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
324         pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
325         pDoc->SetRedlineMode_intern( eOld );
326     }
327     else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
328             pDoc->GetRedlineTbl().Count() )
329         pDoc->SplitRedline( *pPam );
330 }
331 
332 void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext)
333 {
334     SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() );
335     SetPaM( aPam );
336     SwPaM & rRepeatPaM( rContext.GetRepeatPaM() );
337     aPam.GetDoc()->CopyRange( aPam, *rRepeatPaM.GetPoint(), false );
338 }
339 
340 
341 //////////////////////////////////////////////////////////////////////////
342 
343 SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
344     : SwUndoInserts( UNDO_INSDOKUMENT, rPam )
345 {
346 }
347 
348 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
349     : SwUndoInserts( UNDO_COPY, rPam )
350 {
351 }
352 
353