xref: /aoo41x/main/sw/source/core/undo/undel.cxx (revision dec99bbd)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <UndoDelete.hxx>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <hintids.hxx>
30cdf0e10cSrcweir #include <unotools/charclass.hxx>
31cdf0e10cSrcweir #include <editeng/brkitem.hxx>
32cdf0e10cSrcweir #include <fmtpdsc.hxx>
33cdf0e10cSrcweir #include <frmfmt.hxx>
34cdf0e10cSrcweir #include <fmtanchr.hxx>
35cdf0e10cSrcweir #include <doc.hxx>
36cdf0e10cSrcweir #include <UndoManager.hxx>
37cdf0e10cSrcweir #include <swtable.hxx>
38cdf0e10cSrcweir #include <swundo.hxx>			// fuer die UndoIds
39cdf0e10cSrcweir #include <pam.hxx>
40cdf0e10cSrcweir #include <ndtxt.hxx>
41cdf0e10cSrcweir #include <UndoCore.hxx>
42cdf0e10cSrcweir #include <rolbck.hxx>
43cdf0e10cSrcweir #include <poolfmt.hxx>
44cdf0e10cSrcweir #include <mvsave.hxx>
45cdf0e10cSrcweir #include <redline.hxx>
46cdf0e10cSrcweir #include <docary.hxx>
47cdf0e10cSrcweir #include <sfx2/app.hxx>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #include <fldbas.hxx>
50cdf0e10cSrcweir #include <fmtfld.hxx>
51cdf0e10cSrcweir #include <comcore.hrc> // #111827#
52cdf0e10cSrcweir #include <undo.hrc>
53cdf0e10cSrcweir 
54cdf0e10cSrcweir // #include <editeng/svxacorr.hxx>
55cdf0e10cSrcweir // #include <comphelper/processfactory.hxx>
56cdf0e10cSrcweir // #include <editeng/unolingu.hxx>
57cdf0e10cSrcweir // #include <unotools/localedatawrapper.hxx>
58cdf0e10cSrcweir 
59cdf0e10cSrcweir // using namespace comphelper;
60cdf0e10cSrcweir 
61cdf0e10cSrcweir 
62cdf0e10cSrcweir // DELETE
63cdf0e10cSrcweir /*  lcl_MakeAutoFrms has to call MakeFrms for objects bounded "AtChar" ( == AUTO ),
64cdf0e10cSrcweir     if the anchor frame has be moved via _MoveNodes(..) and DelFrms(..)
65cdf0e10cSrcweir */
66cdf0e10cSrcweir 
lcl_MakeAutoFrms(const SwSpzFrmFmts & rSpzArr,sal_uLong nMovedIndex)67cdf0e10cSrcweir void lcl_MakeAutoFrms( const SwSpzFrmFmts& rSpzArr, sal_uLong nMovedIndex )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir     if( rSpzArr.Count() )
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         SwFlyFrmFmt* pFmt;
72cdf0e10cSrcweir         const SwFmtAnchor* pAnchor;
73cdf0e10cSrcweir         for( sal_uInt16 n = 0; n < rSpzArr.Count(); ++n )
74cdf0e10cSrcweir         {
75cdf0e10cSrcweir             pFmt = (SwFlyFrmFmt*)rSpzArr[n];
76cdf0e10cSrcweir             pAnchor = &pFmt->GetAnchor();
77cdf0e10cSrcweir             if (pAnchor->GetAnchorId() == FLY_AT_CHAR)
78cdf0e10cSrcweir             {
79cdf0e10cSrcweir                 const SwPosition* pAPos = pAnchor->GetCntntAnchor();
80cdf0e10cSrcweir                 if( pAPos && nMovedIndex == pAPos->nNode.GetIndex() )
81cdf0e10cSrcweir                     pFmt->MakeFrms();
82cdf0e10cSrcweir             }
83cdf0e10cSrcweir         }
84cdf0e10cSrcweir     }
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir /*
88cdf0e10cSrcweir SwUndoDelete has to perform a deletion and to record anything that is needed to restore the
89cdf0e10cSrcweir situation before the deletion. Unfortunately a part of the deletion will be done after calling
90cdf0e10cSrcweir this Ctor, this has to be kept in mind! In this Ctor only the complete paragraphs will be deleted,
91cdf0e10cSrcweir the joining of the first and last paragraph of the selection will be handled outside this function.
92cdf0e10cSrcweir Here are the main steps of the function:
93cdf0e10cSrcweir 1. Deletion/recording of content indizes of the selection: footnotes, fly frames and bookmarks
94cdf0e10cSrcweir Step 1 could shift all nodes by deletion of footnotes => nNdDiff will be set.
95cdf0e10cSrcweir 2. If the paragraph where the selection ends, is the last content of a section so that this
96cdf0e10cSrcweir section becomes empty when the paragraphs will be joined we have to do some smart actions ;-)
97cdf0e10cSrcweir The paragraph will be moved outside the section and replaced by a dummy text node, the complete
98cdf0e10cSrcweir section will be deleted in step 3. The difference between replacement dummy and original is
99cdf0e10cSrcweir nReplacementDummy.
100cdf0e10cSrcweir 3. Moving complete selected nodes into the UndoArray. Before this happens the selection has to be
101cdf0e10cSrcweir extended if there are sections which would become empty otherwise. BTW: sections will be moved into
102cdf0e10cSrcweir the UndoArray if they are complete part of the selection. Sections starting or ending outside of the
103cdf0e10cSrcweir selection will not be removed from the DocNodeArray even they got a "dummy"-copy in the UndoArray.
104cdf0e10cSrcweir 4. We have to anticipate the joining of the two paragraphs if the start paragraph is inside a
105cdf0e10cSrcweir section and the end paragraph not. Then we have to move the paragraph into this section and to
106cdf0e10cSrcweir record this in nSectDiff.
107cdf0e10cSrcweir */
108cdf0e10cSrcweir 
SwUndoDelete(SwPaM & rPam,sal_Bool bFullPara,sal_Bool bCalledByTblCpy)109*dec99bbdSOliver-Rainer Wittmann SwUndoDelete::SwUndoDelete(
110*dec99bbdSOliver-Rainer Wittmann     SwPaM& rPam,
111*dec99bbdSOliver-Rainer Wittmann     sal_Bool bFullPara,
112*dec99bbdSOliver-Rainer Wittmann     sal_Bool bCalledByTblCpy )
113*dec99bbdSOliver-Rainer Wittmann     : SwUndo(UNDO_DELETE)
114*dec99bbdSOliver-Rainer Wittmann     , SwUndRng( rPam )
115*dec99bbdSOliver-Rainer Wittmann     , pMvStt( 0 )
116*dec99bbdSOliver-Rainer Wittmann     , pSttStr(0)
117*dec99bbdSOliver-Rainer Wittmann     , pEndStr(0)
118*dec99bbdSOliver-Rainer Wittmann     , pRedlData(0)
119*dec99bbdSOliver-Rainer Wittmann     , pRedlSaveData(0)
120*dec99bbdSOliver-Rainer Wittmann     , nNode(0)
121*dec99bbdSOliver-Rainer Wittmann     , nNdDiff(0)
122*dec99bbdSOliver-Rainer Wittmann     , nSectDiff(0)
123*dec99bbdSOliver-Rainer Wittmann     , nReplaceDummy(0)
124*dec99bbdSOliver-Rainer Wittmann     , nSetPos(0)
125*dec99bbdSOliver-Rainer Wittmann     , bGroup( sal_False )
126*dec99bbdSOliver-Rainer Wittmann     , bBackSp( sal_False )
127*dec99bbdSOliver-Rainer Wittmann     , bJoinNext( sal_False )
128*dec99bbdSOliver-Rainer Wittmann     , bTblDelLastNd( sal_False )
129*dec99bbdSOliver-Rainer Wittmann     , bDelFullPara( bFullPara )
130*dec99bbdSOliver-Rainer Wittmann     , bResetPgDesc( sal_False )
131*dec99bbdSOliver-Rainer Wittmann     , bResetPgBrk( sal_False )
132*dec99bbdSOliver-Rainer Wittmann     , bFromTableCopy( bCalledByTblCpy )
133cdf0e10cSrcweir {
134cdf0e10cSrcweir 	bDelFullPara = bFullPara; // This is set e.g. if an empty paragraph before a table is deleted
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     bCacheComment = false;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir 	SwDoc * pDoc = rPam.GetDoc();
139cdf0e10cSrcweir 
140cdf0e10cSrcweir 	if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
141cdf0e10cSrcweir 	{
142cdf0e10cSrcweir 		pRedlSaveData = new SwRedlineSaveDatas;
143cdf0e10cSrcweir 		if( !FillSaveData( rPam, *pRedlSaveData ))
144cdf0e10cSrcweir 			delete pRedlSaveData, pRedlSaveData = 0;
145cdf0e10cSrcweir 	}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	if( !pHistory )
148cdf0e10cSrcweir 		pHistory = new SwHistory;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 	// loesche erstmal alle Fussnoten
151cdf0e10cSrcweir 	const SwPosition *pStt = rPam.Start(),
152cdf0e10cSrcweir 					*pEnd = rPam.GetPoint() == pStt
153cdf0e10cSrcweir 						? rPam.GetMark()
154cdf0e10cSrcweir 						: rPam.GetPoint();
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     // Step 1. deletion/record of content indizes
157cdf0e10cSrcweir 	if( bDelFullPara )
158cdf0e10cSrcweir 	{
159cdf0e10cSrcweir 		ASSERT( rPam.HasMark(), "PaM ohne Mark" );
160cdf0e10cSrcweir 		DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
161cdf0e10cSrcweir                         DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
162cdf0e10cSrcweir 
163cdf0e10cSrcweir         ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
164cdf0e10cSrcweir 		_DelBookmarks(pStt->nNode, pEnd->nNode);
165cdf0e10cSrcweir 	}
166cdf0e10cSrcweir 	else
167cdf0e10cSrcweir 		DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir 	nSetPos = pHistory ? pHistory->Count() : 0;
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 	// wurde schon was geloescht ??
172cdf0e10cSrcweir 	nNdDiff = nSttNode - pStt->nNode.GetIndex();
173cdf0e10cSrcweir 
174cdf0e10cSrcweir 	bJoinNext = !bFullPara && pEnd == rPam.GetPoint();
175cdf0e10cSrcweir 	bBackSp = !bFullPara && !bJoinNext;
176cdf0e10cSrcweir 
177cdf0e10cSrcweir 	SwTxtNode *pSttTxtNd = 0, *pEndTxtNd = 0;
178cdf0e10cSrcweir 	if( !bFullPara )
179cdf0e10cSrcweir 	{
180cdf0e10cSrcweir 		pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
181cdf0e10cSrcweir 		pEndTxtNd = nSttNode == nEndNode
182cdf0e10cSrcweir 					? pSttTxtNd
183cdf0e10cSrcweir 					: pEnd->nNode.GetNode().GetTxtNode();
184cdf0e10cSrcweir 	}
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 	sal_Bool bMoveNds = *pStt == *pEnd      // noch ein Bereich vorhanden ??
187cdf0e10cSrcweir 				? sal_False
188cdf0e10cSrcweir 				: ( SaveCntnt( pStt, pEnd, pSttTxtNd, pEndTxtNd ) || bFromTableCopy );
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 	if( pSttTxtNd && pEndTxtNd && pSttTxtNd != pEndTxtNd )
191cdf0e10cSrcweir 	{
192cdf0e10cSrcweir 		// zwei unterschiedliche TextNodes, also speicher noch die
193cdf0e10cSrcweir 		// TextFormatCollection fuers
194cdf0e10cSrcweir 		pHistory->Add( pSttTxtNd->GetTxtColl(),pStt->nNode.GetIndex(), ND_TEXTNODE );
195cdf0e10cSrcweir 		pHistory->Add( pEndTxtNd->GetTxtColl(),pEnd->nNode.GetIndex(), ND_TEXTNODE );
196cdf0e10cSrcweir 
197cdf0e10cSrcweir 		if( !bJoinNext )	 	// Selection von Unten nach Oben
198cdf0e10cSrcweir 		{
199cdf0e10cSrcweir 			// Beim JoinPrev() werden die AUTO-PageBreak's richtig
200cdf0e10cSrcweir 			// kopiert. Um diese beim Undo wieder herzustellen, muss das
201cdf0e10cSrcweir 			// Auto-PageBreak aus dem EndNode zurueckgesetzt werden.
202cdf0e10cSrcweir 			// - fuer die PageDesc, ColBreak dito !
203cdf0e10cSrcweir             if( pEndTxtNd->HasSwAttrSet() )
204cdf0e10cSrcweir 			{
205cdf0e10cSrcweir 				SwRegHistory aRegHist( *pEndTxtNd, pHistory );
206cdf0e10cSrcweir 				if( SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
207cdf0e10cSrcweir 						RES_BREAK, sal_False ) )
208cdf0e10cSrcweir 					pEndTxtNd->ResetAttr( RES_BREAK );
209cdf0e10cSrcweir                 if( pEndTxtNd->HasSwAttrSet() &&
210cdf0e10cSrcweir 					SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
211cdf0e10cSrcweir 						RES_PAGEDESC, sal_False ) )
212cdf0e10cSrcweir 					pEndTxtNd->ResetAttr( RES_PAGEDESC );
213cdf0e10cSrcweir 			}
214cdf0e10cSrcweir 		}
215cdf0e10cSrcweir 	}
216cdf0e10cSrcweir 
217cdf0e10cSrcweir 
218cdf0e10cSrcweir 	// verschiebe jetzt noch den PaM !!!
219cdf0e10cSrcweir 	// der SPoint steht am Anfang der SSelection
220cdf0e10cSrcweir 	if( pEnd == rPam.GetPoint() && ( !bFullPara || pSttTxtNd || pEndTxtNd ) )
221cdf0e10cSrcweir 		rPam.Exchange();
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 	if( !pSttTxtNd && !pEndTxtNd )
224cdf0e10cSrcweir 		rPam.GetPoint()->nNode--;
225cdf0e10cSrcweir 	rPam.DeleteMark();			// der SPoint ist aus dem Bereich
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 	if( !pEndTxtNd )
228cdf0e10cSrcweir 		nEndCntnt = 0;
229cdf0e10cSrcweir 	if( !pSttTxtNd )
230cdf0e10cSrcweir 		nSttCntnt = 0;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 	if( bMoveNds )		// sind noch Nodes zu verschieben ?
233cdf0e10cSrcweir     {
234cdf0e10cSrcweir         SwNodes& rNds = pDoc->GetUndoManager().GetUndoNodes();
235cdf0e10cSrcweir 		SwNodes& rDocNds = pDoc->GetNodes();
236cdf0e10cSrcweir 		SwNodeRange aRg( rDocNds, nSttNode - nNdDiff,
237cdf0e10cSrcweir 						 rDocNds, nEndNode - nNdDiff );
238cdf0e10cSrcweir 		if( !bFullPara && !pEndTxtNd &&
239cdf0e10cSrcweir 			&aRg.aEnd.GetNode() != &pDoc->GetNodes().GetEndOfContent() )
240cdf0e10cSrcweir         {
241cdf0e10cSrcweir             SwNode* pNode = aRg.aEnd.GetNode().StartOfSectionNode();
242cdf0e10cSrcweir             if( pNode->GetIndex() >= nSttNode - nNdDiff )
243cdf0e10cSrcweir                 aRg.aEnd++; // Deletion of a complete table
244cdf0e10cSrcweir         }
245cdf0e10cSrcweir 		SwNode* pTmpNd;
246cdf0e10cSrcweir         // Step 2: Expand selection if necessary
247cdf0e10cSrcweir         if( bJoinNext || bFullPara )
248cdf0e10cSrcweir         {
249cdf0e10cSrcweir             // If all content of a section will be moved into Undo,
250cdf0e10cSrcweir             // the section itself should be moved complete.
251cdf0e10cSrcweir 			while( aRg.aEnd.GetIndex() + 2  < rDocNds.Count() &&
252cdf0e10cSrcweir 				( (pTmpNd = rDocNds[ aRg.aEnd.GetIndex()+1 ])->IsEndNode() &&
253cdf0e10cSrcweir                 pTmpNd->StartOfSectionNode()->IsSectionNode() &&
254cdf0e10cSrcweir                 pTmpNd->StartOfSectionNode()->GetIndex() >= aRg.aStart.GetIndex() ) )
255cdf0e10cSrcweir 				aRg.aEnd++;
256cdf0e10cSrcweir             nReplaceDummy = aRg.aEnd.GetIndex() + nNdDiff - nEndNode;
257cdf0e10cSrcweir             if( nReplaceDummy )
258cdf0e10cSrcweir             {   // The selection has been expanded, because
259cdf0e10cSrcweir                 aRg.aEnd++;
260cdf0e10cSrcweir                 if( pEndTxtNd )
261cdf0e10cSrcweir                 {
262cdf0e10cSrcweir                     // The end text node has to leave the (expanded) selection
263cdf0e10cSrcweir                     // The dummy is needed because _MoveNodes deletes empty sections
264cdf0e10cSrcweir                     ++nReplaceDummy;
265cdf0e10cSrcweir                     SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
266cdf0e10cSrcweir                     SwPosition aSplitPos( *pEndTxtNd );
267cdf0e10cSrcweir                     ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
268cdf0e10cSrcweir                     pDoc->SplitNode( aSplitPos, false );
269cdf0e10cSrcweir                     rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
270cdf0e10cSrcweir                     aRg.aEnd--;
271cdf0e10cSrcweir                 }
272cdf0e10cSrcweir                 else
273cdf0e10cSrcweir                     nReplaceDummy = 0;
274cdf0e10cSrcweir             }
275cdf0e10cSrcweir         }
276cdf0e10cSrcweir         if( bBackSp || bFullPara )
277cdf0e10cSrcweir         {
278cdf0e10cSrcweir             //See above, the selection has to expanded if there are "nearly empty" sections
279cdf0e10cSrcweir             // and a replacement dummy has to be set if needed.
280cdf0e10cSrcweir 			while( 1 < aRg.aStart.GetIndex() &&
281cdf0e10cSrcweir 				( (pTmpNd = rDocNds[ aRg.aStart.GetIndex()-1 ])->IsSectionNode() &&
282cdf0e10cSrcweir 				pTmpNd->EndOfSectionIndex() < aRg.aEnd.GetIndex() ) )
283cdf0e10cSrcweir 				aRg.aStart--;
284cdf0e10cSrcweir             if( pSttTxtNd )
285cdf0e10cSrcweir             {
286cdf0e10cSrcweir                 nReplaceDummy = nSttNode - nNdDiff - aRg.aStart.GetIndex();
287cdf0e10cSrcweir                 if( nReplaceDummy )
288cdf0e10cSrcweir                 {
289cdf0e10cSrcweir                     SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
290cdf0e10cSrcweir                     SwPosition aSplitPos( *pSttTxtNd );
291cdf0e10cSrcweir                     ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
292cdf0e10cSrcweir                     pDoc->SplitNode( aSplitPos, false );
293cdf0e10cSrcweir                     rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
294cdf0e10cSrcweir 					aRg.aStart--;
295cdf0e10cSrcweir                 }
296cdf0e10cSrcweir             }
297cdf0e10cSrcweir         }
298cdf0e10cSrcweir 
299cdf0e10cSrcweir         if( bFromTableCopy )
300cdf0e10cSrcweir         {
301cdf0e10cSrcweir             if( !pEndTxtNd )
302cdf0e10cSrcweir             {
303cdf0e10cSrcweir                 if( pSttTxtNd )
304cdf0e10cSrcweir                     aRg.aStart++;
305cdf0e10cSrcweir                 else if( !bFullPara && !aRg.aEnd.GetNode().IsCntntNode() )
306cdf0e10cSrcweir                     aRg.aEnd--;
307cdf0e10cSrcweir             }
308cdf0e10cSrcweir         }
309cdf0e10cSrcweir         else if( pSttTxtNd && ( pEndTxtNd || pSttTxtNd->GetTxt().Len() ) )
310cdf0e10cSrcweir             aRg.aStart++;
311cdf0e10cSrcweir 
312cdf0e10cSrcweir         // Step 3: Moving into UndoArray...
313cdf0e10cSrcweir 		nNode = rNds.GetEndOfContent().GetIndex();
314cdf0e10cSrcweir 		rDocNds._MoveNodes( aRg, rNds, SwNodeIndex( rNds.GetEndOfContent() ));
315cdf0e10cSrcweir 		pMvStt = new SwNodeIndex( rNds, nNode );
316cdf0e10cSrcweir 		nNode = rNds.GetEndOfContent().GetIndex() - nNode;		// Differenz merken !
317cdf0e10cSrcweir         if( pSttTxtNd && pEndTxtNd )
318cdf0e10cSrcweir         {
319cdf0e10cSrcweir             //Step 4: Moving around sections
320cdf0e10cSrcweir             nSectDiff = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
321cdf0e10cSrcweir             // nSect is the number of sections which starts(ends) between start and end node of the
322cdf0e10cSrcweir             // selection. The "loser" paragraph has to be moved into the section(s) of the
323cdf0e10cSrcweir             // "winner" paragraph
324cdf0e10cSrcweir             if( nSectDiff )
325cdf0e10cSrcweir             {
326cdf0e10cSrcweir                 if( bJoinNext )
327cdf0e10cSrcweir                 {
328cdf0e10cSrcweir                     SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
329cdf0e10cSrcweir                     rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
330cdf0e10cSrcweir                 }
331cdf0e10cSrcweir                 else
332cdf0e10cSrcweir                 {
333cdf0e10cSrcweir                     SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
334cdf0e10cSrcweir                     rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
335cdf0e10cSrcweir                 }
336cdf0e10cSrcweir             }
337cdf0e10cSrcweir         }
338cdf0e10cSrcweir         if( nSectDiff || nReplaceDummy )
339cdf0e10cSrcweir             lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(),
340cdf0e10cSrcweir                 bJoinNext ? pEndTxtNd->GetIndex() : pSttTxtNd->GetIndex() );
341cdf0e10cSrcweir 	}
342cdf0e10cSrcweir 	else
343cdf0e10cSrcweir 		nNode = 0;		// kein Node verschoben -> keine Differenz zum Ende
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 	// wurden davor noch Nodes geloescht ?? (FootNotes haben ContentNodes!)
346cdf0e10cSrcweir 	if( !pSttTxtNd && !pEndTxtNd )
347cdf0e10cSrcweir 	{
348cdf0e10cSrcweir 		nNdDiff = nSttNode - rPam.GetPoint()->nNode.GetIndex() - (bFullPara ? 0 : 1);
349cdf0e10cSrcweir 		rPam.Move( fnMoveForward, fnGoNode );
350cdf0e10cSrcweir 	}
351cdf0e10cSrcweir 	else
352cdf0e10cSrcweir     {
353cdf0e10cSrcweir 		nNdDiff = nSttNode;
354cdf0e10cSrcweir         if( nSectDiff && bBackSp )
355cdf0e10cSrcweir             nNdDiff += nSectDiff;
356cdf0e10cSrcweir         nNdDiff -= rPam.GetPoint()->nNode.GetIndex();
357cdf0e10cSrcweir     }
358cdf0e10cSrcweir 
359cdf0e10cSrcweir 	if( !rPam.GetNode()->IsCntntNode() )
360cdf0e10cSrcweir 		rPam.GetPoint()->nContent.Assign( 0, 0 );
361cdf0e10cSrcweir 
362cdf0e10cSrcweir 	// wird die History ueberhaupt benoetigt ??
363cdf0e10cSrcweir 	if( pHistory && !pHistory->Count() )
364cdf0e10cSrcweir 		DELETEZ( pHistory );
365cdf0e10cSrcweir }
366cdf0e10cSrcweir 
SaveCntnt(const SwPosition * pStt,const SwPosition * pEnd,SwTxtNode * pSttTxtNd,SwTxtNode * pEndTxtNd)367cdf0e10cSrcweir sal_Bool SwUndoDelete::SaveCntnt( const SwPosition* pStt, const SwPosition* pEnd,
368cdf0e10cSrcweir 					SwTxtNode* pSttTxtNd, SwTxtNode* pEndTxtNd )
369cdf0e10cSrcweir {
370cdf0e10cSrcweir 	sal_uLong nNdIdx = pStt->nNode.GetIndex();
371cdf0e10cSrcweir 	// 1 - kopiere den Anfang in den Start-String
372cdf0e10cSrcweir 	if( pSttTxtNd )
373cdf0e10cSrcweir 	{
374cdf0e10cSrcweir 		sal_Bool bOneNode = nSttNode == nEndNode;
375cdf0e10cSrcweir 		xub_StrLen nLen = bOneNode ? nEndCntnt - nSttCntnt
376cdf0e10cSrcweir 								: pSttTxtNd->GetTxt().Len() - nSttCntnt;
377cdf0e10cSrcweir 		SwRegHistory aRHst( *pSttTxtNd, pHistory );
378cdf0e10cSrcweir         // always save all text atttibutes because of possibly overlapping
379cdf0e10cSrcweir         // areas of on/off
380cdf0e10cSrcweir         pHistory->CopyAttr( pSttTxtNd->GetpSwpHints(), nNdIdx,
381cdf0e10cSrcweir                             0, pSttTxtNd->GetTxt().Len(), true );
382cdf0e10cSrcweir         if( !bOneNode && pSttTxtNd->HasSwAttrSet() )
383cdf0e10cSrcweir                 pHistory->CopyFmtAttr( *pSttTxtNd->GetpSwAttrSet(), nNdIdx );
384cdf0e10cSrcweir 
385cdf0e10cSrcweir 		// die Laenge kann sich veraendert haben (!!Felder!!)
386cdf0e10cSrcweir 		nLen = ( bOneNode ? pEnd->nContent.GetIndex() : pSttTxtNd->GetTxt().Len() )
387cdf0e10cSrcweir 				- pStt->nContent.GetIndex();
388cdf0e10cSrcweir 
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 		// loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
391cdf0e10cSrcweir 		// die Undo-History
392cdf0e10cSrcweir 		pSttStr = (String*)new String( pSttTxtNd->GetTxt().Copy( nSttCntnt, nLen ));
393cdf0e10cSrcweir         pSttTxtNd->EraseText( pStt->nContent, nLen );
394cdf0e10cSrcweir 		if( pSttTxtNd->GetpSwpHints() )
395cdf0e10cSrcweir 			pSttTxtNd->GetpSwpHints()->DeRegister();
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         // METADATA: store
398cdf0e10cSrcweir         bool emptied( pSttStr->Len() && !pSttTxtNd->Len() );
399cdf0e10cSrcweir         if (!bOneNode || emptied) // merging may overwrite xmlids...
400cdf0e10cSrcweir         {
401cdf0e10cSrcweir             m_pMetadataUndoStart = (emptied)
402cdf0e10cSrcweir                 ? pSttTxtNd->CreateUndoForDelete()
403cdf0e10cSrcweir                 : pSttTxtNd->CreateUndo();
404cdf0e10cSrcweir         }
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 		if( bOneNode )
407cdf0e10cSrcweir 			return sal_False;           // keine Nodes mehr verschieben
408cdf0e10cSrcweir 	}
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 
411cdf0e10cSrcweir 	// 2 - kopiere das Ende in den End-String
412cdf0e10cSrcweir 	if( pEndTxtNd )
413cdf0e10cSrcweir 	{
414cdf0e10cSrcweir 		SwIndex aEndIdx( pEndTxtNd );
415cdf0e10cSrcweir 		nNdIdx = pEnd->nNode.GetIndex();
416cdf0e10cSrcweir 		SwRegHistory aRHst( *pEndTxtNd, pHistory );
417cdf0e10cSrcweir 
418cdf0e10cSrcweir         // always save all text atttibutes because of possibly overlapping
419cdf0e10cSrcweir         // areas of on/off
420cdf0e10cSrcweir         pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nNdIdx, 0,
421cdf0e10cSrcweir                             pEndTxtNd->GetTxt().Len(), true );
422cdf0e10cSrcweir 
423cdf0e10cSrcweir         if( pEndTxtNd->HasSwAttrSet() )
424cdf0e10cSrcweir             pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nNdIdx );
425cdf0e10cSrcweir 
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 		// loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
428cdf0e10cSrcweir 		// die Undo-History
429cdf0e10cSrcweir 		pEndStr = (String*)new String( pEndTxtNd->GetTxt().Copy( 0,
430cdf0e10cSrcweir 									pEnd->nContent.GetIndex() ));
431cdf0e10cSrcweir         pEndTxtNd->EraseText( aEndIdx, pEnd->nContent.GetIndex() );
432cdf0e10cSrcweir 		if( pEndTxtNd->GetpSwpHints() )
433cdf0e10cSrcweir 			pEndTxtNd->GetpSwpHints()->DeRegister();
434cdf0e10cSrcweir 
435cdf0e10cSrcweir         // METADATA: store
436cdf0e10cSrcweir         bool emptied( pEndStr->Len() && !pEndTxtNd->Len() );
437cdf0e10cSrcweir 
438cdf0e10cSrcweir         m_pMetadataUndoEnd = (emptied)
439cdf0e10cSrcweir             ? pEndTxtNd->CreateUndoForDelete()
440cdf0e10cSrcweir             : pEndTxtNd->CreateUndo();
441cdf0e10cSrcweir     }
442cdf0e10cSrcweir 
443cdf0e10cSrcweir 	// sind es nur zwei Nodes, dann ist schon alles erledigt.
444cdf0e10cSrcweir 	if( ( pSttTxtNd || pEndTxtNd ) && nSttNode + 1 == nEndNode )
445cdf0e10cSrcweir 		return sal_False;           // keine Nodes mehr verschieben
446cdf0e10cSrcweir 
447cdf0e10cSrcweir 	return sal_True;                // verschiebe die dazwischen liegenden Nodes
448cdf0e10cSrcweir }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 
CanGrouping(SwDoc * pDoc,const SwPaM & rDelPam)451cdf0e10cSrcweir sal_Bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
452cdf0e10cSrcweir {
453cdf0e10cSrcweir 	// ist das Undo groesser als 1 Node ? (sprich: Start und EndString)
454cdf0e10cSrcweir 	if( pSttStr ? !pSttStr->Len() || pEndStr : sal_True )
455cdf0e10cSrcweir 		return sal_False;
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 	// es kann nur das Loeschen von einzelnen char's zusammengefasst werden
458cdf0e10cSrcweir 	if( nSttNode != nEndNode || ( !bGroup && nSttCntnt+1 != nEndCntnt ))
459cdf0e10cSrcweir 		return sal_False;
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 	const SwPosition *pStt = rDelPam.Start(),
462cdf0e10cSrcweir 					*pEnd = rDelPam.GetPoint() == pStt
463cdf0e10cSrcweir 						? rDelPam.GetMark()
464cdf0e10cSrcweir 						: rDelPam.GetPoint();
465cdf0e10cSrcweir 
466cdf0e10cSrcweir 	if( pStt->nNode != pEnd->nNode ||
467cdf0e10cSrcweir 		pStt->nContent.GetIndex()+1 != pEnd->nContent.GetIndex() ||
468cdf0e10cSrcweir 		pEnd->nNode != nSttNode )
469cdf0e10cSrcweir 		return sal_False;
470cdf0e10cSrcweir 
471cdf0e10cSrcweir 	// untercheide zwischen BackSpace und Delete. Es muss dann das
472cdf0e10cSrcweir 	// Undo-Array unterschiedlich aufgebaut werden !!
473cdf0e10cSrcweir 	if( pEnd->nContent == nSttCntnt )
474cdf0e10cSrcweir 	{
475cdf0e10cSrcweir 		if( bGroup && !bBackSp ) return sal_False;
476cdf0e10cSrcweir 		bBackSp = sal_True;
477cdf0e10cSrcweir 	}
478cdf0e10cSrcweir 	else if( pStt->nContent == nSttCntnt )
479cdf0e10cSrcweir 	{
480cdf0e10cSrcweir 		if( bGroup && bBackSp ) return sal_False;
481cdf0e10cSrcweir 		bBackSp = sal_False;
482cdf0e10cSrcweir 	}
483cdf0e10cSrcweir 	else
484cdf0e10cSrcweir 		return sal_False;
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 	// sind die beiden Nodes (Nodes-/Undo-Array) ueberhaupt TextNodes?
487cdf0e10cSrcweir 	SwTxtNode * pDelTxtNd = pStt->nNode.GetNode().GetTxtNode();
488cdf0e10cSrcweir 	if( !pDelTxtNd ) return sal_False;
489cdf0e10cSrcweir 
490cdf0e10cSrcweir 	xub_StrLen nUChrPos = bBackSp ? 0 : pSttStr->Len()-1;
491cdf0e10cSrcweir 	sal_Unicode cDelChar = pDelTxtNd->GetTxt().GetChar( pStt->nContent.GetIndex() );
492cdf0e10cSrcweir 	CharClass& rCC = GetAppCharClass();
493cdf0e10cSrcweir 	if( ( CH_TXTATR_BREAKWORD == cDelChar || CH_TXTATR_INWORD == cDelChar ) ||
494cdf0e10cSrcweir 		rCC.isLetterNumeric( String( cDelChar ), 0 ) !=
495cdf0e10cSrcweir 		rCC.isLetterNumeric( *pSttStr, nUChrPos ) )
496cdf0e10cSrcweir 		return sal_False;
497cdf0e10cSrcweir 
498cdf0e10cSrcweir 	{
499cdf0e10cSrcweir 		SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
500cdf0e10cSrcweir 		if( !FillSaveData( rDelPam, *pTmpSav, sal_False ))
501cdf0e10cSrcweir 			delete pTmpSav, pTmpSav = 0;
502cdf0e10cSrcweir 
503cdf0e10cSrcweir 		sal_Bool bOk = ( !pRedlSaveData && !pTmpSav ) ||
504cdf0e10cSrcweir 				   ( pRedlSaveData && pTmpSav &&
505cdf0e10cSrcweir 				SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav, bBackSp ));
506cdf0e10cSrcweir 		delete pTmpSav;
507cdf0e10cSrcweir 		if( !bOk )
508cdf0e10cSrcweir 			return sal_False;
509cdf0e10cSrcweir 
510cdf0e10cSrcweir         pDoc->DeleteRedline( rDelPam, false, USHRT_MAX );
511cdf0e10cSrcweir 	}
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 	// Ok, die beiden 'Deletes' koennen zusammen gefasst werden, also
514cdf0e10cSrcweir 	// 'verschiebe' das enstprechende Zeichen
515cdf0e10cSrcweir 	if( bBackSp )
516cdf0e10cSrcweir 		nSttCntnt--;    // BackSpace: Zeichen in Array einfuegen !!
517cdf0e10cSrcweir 	else
518cdf0e10cSrcweir 	{
519cdf0e10cSrcweir 		nEndCntnt++;    // Delete: Zeichen am Ende anhaengen
520cdf0e10cSrcweir 		nUChrPos++;
521cdf0e10cSrcweir 	}
522cdf0e10cSrcweir 	pSttStr->Insert( cDelChar, nUChrPos );
523cdf0e10cSrcweir     pDelTxtNd->EraseText( pStt->nContent, 1 );
524cdf0e10cSrcweir 
525cdf0e10cSrcweir 	bGroup = sal_True;
526cdf0e10cSrcweir 	return sal_True;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 
~SwUndoDelete()531cdf0e10cSrcweir SwUndoDelete::~SwUndoDelete()
532cdf0e10cSrcweir {
533cdf0e10cSrcweir 	delete pSttStr;
534cdf0e10cSrcweir 	delete pEndStr;
535cdf0e10cSrcweir 	if( pMvStt )		// loesche noch den Bereich aus dem UndoNodes Array
536cdf0e10cSrcweir 	{
537cdf0e10cSrcweir 		// Insert speichert den Inhalt in der IconSection
538cdf0e10cSrcweir 		pMvStt->GetNode().GetNodes().Delete( *pMvStt, nNode );
539cdf0e10cSrcweir 		delete pMvStt;
540cdf0e10cSrcweir 	}
541cdf0e10cSrcweir 	delete pRedlData;
542cdf0e10cSrcweir 	delete pRedlSaveData;
543cdf0e10cSrcweir }
544cdf0e10cSrcweir 
lcl_RewriterFromHistory(SwHistory & rHistory)545cdf0e10cSrcweir static SwRewriter lcl_RewriterFromHistory(SwHistory & rHistory)
546cdf0e10cSrcweir {
547cdf0e10cSrcweir     SwRewriter aRewriter;
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     bool bDone = false;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir     for ( sal_uInt16 n = 0; n < rHistory.Count(); n++)
552cdf0e10cSrcweir     {
553cdf0e10cSrcweir         String aDescr = rHistory[n]->GetDescription();
554cdf0e10cSrcweir 
555cdf0e10cSrcweir         if (aDescr.Len() > 0)
556cdf0e10cSrcweir         {
557cdf0e10cSrcweir             aRewriter.AddRule(UNDO_ARG2, aDescr);
558cdf0e10cSrcweir 
559cdf0e10cSrcweir             bDone = true;
560cdf0e10cSrcweir             break;
561cdf0e10cSrcweir         }
562cdf0e10cSrcweir     }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir     if (! bDone)
565cdf0e10cSrcweir     {
566cdf0e10cSrcweir         aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_FIELD));
567cdf0e10cSrcweir     }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     return aRewriter;
570cdf0e10cSrcweir }
571cdf0e10cSrcweir 
GetRewriter() const572cdf0e10cSrcweir SwRewriter SwUndoDelete::GetRewriter() const
573cdf0e10cSrcweir {
574cdf0e10cSrcweir     SwRewriter aResult;
575cdf0e10cSrcweir     String * pStr = NULL;
576cdf0e10cSrcweir 
577cdf0e10cSrcweir     if (nNode != 0)
578cdf0e10cSrcweir     {
579cdf0e10cSrcweir         if (sTableName.Len() > 0)
580cdf0e10cSrcweir         {
581cdf0e10cSrcweir 
582cdf0e10cSrcweir             SwRewriter aRewriter;
583cdf0e10cSrcweir             aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
584cdf0e10cSrcweir             aRewriter.AddRule(UNDO_ARG2, sTableName);
585cdf0e10cSrcweir             aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
586cdf0e10cSrcweir 
587cdf0e10cSrcweir             String sTmp = aRewriter.Apply(SW_RES(STR_TABLE_NAME));
588cdf0e10cSrcweir             aResult.AddRule(UNDO_ARG1, sTmp);
589cdf0e10cSrcweir         }
590cdf0e10cSrcweir         else
591cdf0e10cSrcweir             aResult.AddRule(UNDO_ARG1, String(SW_RES(STR_PARAGRAPHS)));
592cdf0e10cSrcweir     }
593cdf0e10cSrcweir     else
594cdf0e10cSrcweir     {
595cdf0e10cSrcweir         String aStr;
596cdf0e10cSrcweir 
597cdf0e10cSrcweir         if (pSttStr != NULL && pEndStr != NULL && pSttStr->Len() == 0 &&
598cdf0e10cSrcweir             pEndStr->Len() == 0)
599cdf0e10cSrcweir         {
600cdf0e10cSrcweir             aStr = SW_RES(STR_PARAGRAPH_UNDO);
601cdf0e10cSrcweir         }
602cdf0e10cSrcweir         else
603cdf0e10cSrcweir         {
604cdf0e10cSrcweir             if (pSttStr != NULL)
605cdf0e10cSrcweir                 pStr = pSttStr;
606cdf0e10cSrcweir             else if (pEndStr != NULL)
607cdf0e10cSrcweir                 pStr = pEndStr;
608cdf0e10cSrcweir 
609cdf0e10cSrcweir             if (pStr != NULL)
610cdf0e10cSrcweir             {
611cdf0e10cSrcweir                 aStr = DenoteSpecialCharacters(*pStr);
612cdf0e10cSrcweir             }
613cdf0e10cSrcweir             else
614cdf0e10cSrcweir             {
615cdf0e10cSrcweir                 aStr = UNDO_ARG2;
616cdf0e10cSrcweir             }
617cdf0e10cSrcweir         }
618cdf0e10cSrcweir 
619cdf0e10cSrcweir         aStr = ShortenString(aStr, nUndoStringLength, String(SW_RES(STR_LDOTS)));
620cdf0e10cSrcweir         if (pHistory)
621cdf0e10cSrcweir         {
622cdf0e10cSrcweir             SwRewriter aRewriter = lcl_RewriterFromHistory(*pHistory);
623cdf0e10cSrcweir             aStr = aRewriter.Apply(aStr);
624cdf0e10cSrcweir         }
625cdf0e10cSrcweir 
626cdf0e10cSrcweir         aResult.AddRule(UNDO_ARG1, aStr);
627cdf0e10cSrcweir     }
628cdf0e10cSrcweir 
629cdf0e10cSrcweir     return aResult;
630cdf0e10cSrcweir }
631cdf0e10cSrcweir 
632cdf0e10cSrcweir // Every object, anchored "AtCntnt" will be reanchored at rPos
lcl_ReAnchorAtCntntFlyFrames(const SwSpzFrmFmts & rSpzArr,SwPosition & rPos,sal_uLong nOldIdx)633cdf0e10cSrcweir void lcl_ReAnchorAtCntntFlyFrames( const SwSpzFrmFmts& rSpzArr, SwPosition &rPos, sal_uLong nOldIdx )
634cdf0e10cSrcweir {
635cdf0e10cSrcweir     if( rSpzArr.Count() )
636cdf0e10cSrcweir     {
637cdf0e10cSrcweir         SwFlyFrmFmt* pFmt;
638cdf0e10cSrcweir         const SwFmtAnchor* pAnchor;
639cdf0e10cSrcweir         const SwPosition* pAPos;
640cdf0e10cSrcweir         for( sal_uInt16 n = 0; n < rSpzArr.Count(); ++n )
641cdf0e10cSrcweir         {
642cdf0e10cSrcweir             pFmt = (SwFlyFrmFmt*)rSpzArr[n];
643cdf0e10cSrcweir             pAnchor = &pFmt->GetAnchor();
644cdf0e10cSrcweir             if (pAnchor->GetAnchorId() == FLY_AT_PARA)
645cdf0e10cSrcweir             {
646cdf0e10cSrcweir                 pAPos =  pAnchor->GetCntntAnchor();
647cdf0e10cSrcweir                 if( pAPos && nOldIdx == pAPos->nNode.GetIndex() )
648cdf0e10cSrcweir                 {
649cdf0e10cSrcweir                     SwFmtAnchor aAnch( *pAnchor );
650cdf0e10cSrcweir                     aAnch.SetAnchor( &rPos );
651cdf0e10cSrcweir                     pFmt->SetFmtAttr( aAnch );
652cdf0e10cSrcweir                 }
653cdf0e10cSrcweir             }
654cdf0e10cSrcweir         }
655cdf0e10cSrcweir     }
656cdf0e10cSrcweir }
657cdf0e10cSrcweir 
UndoImpl(::sw::UndoRedoContext & rContext)658cdf0e10cSrcweir void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
659cdf0e10cSrcweir {
660cdf0e10cSrcweir     SwDoc *const pDoc = & rContext.GetDoc();
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 	sal_uLong nCalcStt = nSttNode - nNdDiff;
663cdf0e10cSrcweir 
664cdf0e10cSrcweir     if( nSectDiff && bBackSp )
665cdf0e10cSrcweir         nCalcStt += nSectDiff;
666cdf0e10cSrcweir 
667cdf0e10cSrcweir 	SwNodeIndex aIdx( pDoc->GetNodes(), nCalcStt );
668cdf0e10cSrcweir 	SwNode* pInsNd = &aIdx.GetNode();
669cdf0e10cSrcweir 
670cdf0e10cSrcweir 	{		// Block, damit der SwPosition beim loeschen vom Node
671cdf0e10cSrcweir 			// abgemeldet ist
672cdf0e10cSrcweir 		SwPosition aPos( aIdx );
673cdf0e10cSrcweir 		if( !bDelFullPara )
674cdf0e10cSrcweir 		{
675cdf0e10cSrcweir 			if( pInsNd->IsTableNode() )
676cdf0e10cSrcweir 			{
677cdf0e10cSrcweir 				pInsNd = pDoc->GetNodes().MakeTxtNode( aIdx,
678cdf0e10cSrcweir 						(SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
679cdf0e10cSrcweir 				aIdx--;
680cdf0e10cSrcweir 				aPos.nNode = aIdx;
681cdf0e10cSrcweir 				aPos.nContent.Assign( pInsNd->GetCntntNode(), nSttCntnt );
682cdf0e10cSrcweir 			}
683cdf0e10cSrcweir 			else
684cdf0e10cSrcweir 			{
685cdf0e10cSrcweir 				if( pInsNd->IsCntntNode() )
686cdf0e10cSrcweir 					aPos.nContent.Assign( (SwCntntNode*)pInsNd, nSttCntnt );
687cdf0e10cSrcweir 				if( !bTblDelLastNd )
688cdf0e10cSrcweir 					pInsNd = 0;			// Node nicht loeschen !!
689cdf0e10cSrcweir 			}
690cdf0e10cSrcweir 		}
691cdf0e10cSrcweir 		else
692cdf0e10cSrcweir 			pInsNd = 0;			// Node nicht loeschen !!
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 		sal_Bool bNodeMove = 0 != nNode;
695cdf0e10cSrcweir 
696cdf0e10cSrcweir 		if( pEndStr )
697cdf0e10cSrcweir 		{
698cdf0e10cSrcweir 			// alle Attribute verwerfen, wurden alle gespeichert!
699cdf0e10cSrcweir 			SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
700cdf0e10cSrcweir 
701cdf0e10cSrcweir             if( pTxtNd && pTxtNd->HasSwAttrSet() )
702cdf0e10cSrcweir                 pTxtNd->ResetAllAttr();
703cdf0e10cSrcweir 
704cdf0e10cSrcweir             if( pTxtNd && pTxtNd->GetpSwpHints() )
705cdf0e10cSrcweir                 pTxtNd->ClearSwpHintsArr( true );
706cdf0e10cSrcweir 
707cdf0e10cSrcweir 			if( pSttStr && !bFromTableCopy )
708cdf0e10cSrcweir 			{
709cdf0e10cSrcweir                 sal_uLong nOldIdx = aPos.nNode.GetIndex();
710cdf0e10cSrcweir                 pDoc->SplitNode( aPos, false );
711cdf0e10cSrcweir                 // After the split all objects are anchored at the first paragraph,
712cdf0e10cSrcweir                 // but the pHistory of the fly frame formats relies on anchoring at
713cdf0e10cSrcweir                 // the start of the selection => selection backwards needs a correction.
714cdf0e10cSrcweir                 if( bBackSp )
715cdf0e10cSrcweir                     lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
716cdf0e10cSrcweir 				pTxtNd = aPos.nNode.GetNode().GetTxtNode();
717cdf0e10cSrcweir 			}
718cdf0e10cSrcweir             if( pTxtNd )
719cdf0e10cSrcweir             {
720cdf0e10cSrcweir                 pTxtNd->InsertText( *pEndStr, aPos.nContent,
721cdf0e10cSrcweir                         IDocumentContentOperations::INS_NOHINTEXPAND );
722cdf0e10cSrcweir                 // METADATA: restore
723cdf0e10cSrcweir                 pTxtNd->RestoreMetadata(m_pMetadataUndoEnd);
724cdf0e10cSrcweir             }
725cdf0e10cSrcweir 		}
726cdf0e10cSrcweir 		else if( pSttStr && bNodeMove )
727cdf0e10cSrcweir 		{
728cdf0e10cSrcweir 			SwTxtNode * pNd = aPos.nNode.GetNode().GetTxtNode();
729cdf0e10cSrcweir 			if( pNd )
730cdf0e10cSrcweir 			{
731cdf0e10cSrcweir 				if( nSttCntnt < pNd->GetTxt().Len() )
732cdf0e10cSrcweir                 {
733cdf0e10cSrcweir                     sal_uLong nOldIdx = aPos.nNode.GetIndex();
734cdf0e10cSrcweir                     pDoc->SplitNode( aPos, false );
735cdf0e10cSrcweir                     if( bBackSp )
736cdf0e10cSrcweir                         lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
737cdf0e10cSrcweir                 }
738cdf0e10cSrcweir                 else
739cdf0e10cSrcweir                     aPos.nNode++;
740cdf0e10cSrcweir 			}
741cdf0e10cSrcweir 		}
742cdf0e10cSrcweir         SwNode* pMovedNode = NULL;
743cdf0e10cSrcweir         if( nSectDiff )
744cdf0e10cSrcweir         {
745cdf0e10cSrcweir             sal_uLong nMoveIndex = aPos.nNode.GetIndex();
746cdf0e10cSrcweir             int nDiff = 0;
747cdf0e10cSrcweir             if( bJoinNext )
748cdf0e10cSrcweir             {
749cdf0e10cSrcweir                 nMoveIndex += nSectDiff + 1;
750cdf0e10cSrcweir                 pMovedNode = &aPos.nNode.GetNode();
751cdf0e10cSrcweir             }
752cdf0e10cSrcweir             else
753cdf0e10cSrcweir             {
754cdf0e10cSrcweir                 nMoveIndex -= nSectDiff + 1;
755cdf0e10cSrcweir                 ++nDiff;
756cdf0e10cSrcweir             }
757cdf0e10cSrcweir             SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
758cdf0e10cSrcweir             SwNodeRange aRg( aPos.nNode, 0 - nDiff, aPos.nNode, 1 - nDiff );
759cdf0e10cSrcweir             aPos.nNode--;
760cdf0e10cSrcweir             if( !bJoinNext )
761cdf0e10cSrcweir                 pMovedNode = &aPos.nNode.GetNode();
762cdf0e10cSrcweir             pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
763cdf0e10cSrcweir             aPos.nNode++;
764cdf0e10cSrcweir         }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 		if( bNodeMove )
767cdf0e10cSrcweir 		{
768cdf0e10cSrcweir 			SwNodeRange aRange( *pMvStt, 0, *pMvStt, nNode );
769cdf0e10cSrcweir 			SwNodeIndex aCopyIndex( aPos.nNode, -1 );
770cdf0e10cSrcweir             pDoc->GetUndoManager().GetUndoNodes()._Copy( aRange, aPos.nNode );
771cdf0e10cSrcweir 
772cdf0e10cSrcweir             if( nReplaceDummy )
773cdf0e10cSrcweir             {
774cdf0e10cSrcweir                 sal_uLong nMoveIndex;
775cdf0e10cSrcweir                 if( bJoinNext )
776cdf0e10cSrcweir                 {
777cdf0e10cSrcweir                     nMoveIndex = nEndNode - nNdDiff;
778cdf0e10cSrcweir                     aPos.nNode = nMoveIndex + nReplaceDummy;
779cdf0e10cSrcweir                 }
780cdf0e10cSrcweir                 else
781cdf0e10cSrcweir                 {
782cdf0e10cSrcweir                     aPos = SwPosition( aCopyIndex );
783cdf0e10cSrcweir                     nMoveIndex = aPos.nNode.GetIndex() + nReplaceDummy + 1;
784cdf0e10cSrcweir                 }
785cdf0e10cSrcweir                 SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
786cdf0e10cSrcweir                 SwNodeRange aRg( aPos.nNode, 0, aPos.nNode, 1 );
787cdf0e10cSrcweir                 pMovedNode = &aPos.nNode.GetNode();
788cdf0e10cSrcweir                 pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
789cdf0e10cSrcweir                 pDoc->GetNodes().Delete( aMvIdx, 1 );
790cdf0e10cSrcweir             }
791cdf0e10cSrcweir 		}
792cdf0e10cSrcweir 
793cdf0e10cSrcweir         if( pMovedNode )
794cdf0e10cSrcweir             lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(), pMovedNode->GetIndex() );
795cdf0e10cSrcweir 
796cdf0e10cSrcweir 		if( pSttStr )
797cdf0e10cSrcweir 		{
798cdf0e10cSrcweir             aPos.nNode = nSttNode - nNdDiff + ( bJoinNext ? 0 : nReplaceDummy );
799cdf0e10cSrcweir 			SwTxtNode * pTxtNd = aPos.nNode.GetNode().GetTxtNode();
800cdf0e10cSrcweir 			// wenn mehr als ein Node geloescht wurde, dann wurden auch
801cdf0e10cSrcweir 			// alle "Node"-Attribute gespeichert
802cdf0e10cSrcweir 
803cdf0e10cSrcweir             if (pTxtNd != NULL)
804cdf0e10cSrcweir             {
805cdf0e10cSrcweir                 if( pTxtNd->HasSwAttrSet() && bNodeMove && !pEndStr )
806cdf0e10cSrcweir                     pTxtNd->ResetAllAttr();
807cdf0e10cSrcweir 
808cdf0e10cSrcweir                 if( pTxtNd->GetpSwpHints() )
809cdf0e10cSrcweir                     pTxtNd->ClearSwpHintsArr( true );
810cdf0e10cSrcweir 
811cdf0e10cSrcweir                 // SectionNode-Modus und von oben nach unten selektiert:
812cdf0e10cSrcweir                 //	-> im StartNode steht noch der Rest vom Join => loeschen
813cdf0e10cSrcweir                 aPos.nContent.Assign( pTxtNd, nSttCntnt );
814cdf0e10cSrcweir                 pTxtNd->InsertText( *pSttStr, aPos.nContent,
815cdf0e10cSrcweir                         IDocumentContentOperations::INS_NOHINTEXPAND );
816cdf0e10cSrcweir                 // METADATA: restore
817cdf0e10cSrcweir                 pTxtNd->RestoreMetadata(m_pMetadataUndoStart);
818cdf0e10cSrcweir             }
819cdf0e10cSrcweir 		}
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 		if( pHistory )
822cdf0e10cSrcweir         {
823cdf0e10cSrcweir             pHistory->TmpRollback( pDoc, nSetPos, false );
824cdf0e10cSrcweir 			if( nSetPos )		// es gab Fussnoten/FlyFrames
825cdf0e10cSrcweir 			{
826cdf0e10cSrcweir 				// gibts ausser diesen noch andere ?
827cdf0e10cSrcweir 				if( nSetPos < pHistory->Count() )
828cdf0e10cSrcweir 				{
829cdf0e10cSrcweir 					// dann sicher die Attribute anderen Attribute
830cdf0e10cSrcweir 					SwHistory aHstr;
831cdf0e10cSrcweir 					aHstr.Move( 0, pHistory, nSetPos );
832cdf0e10cSrcweir 					pHistory->Rollback( pDoc );
833cdf0e10cSrcweir 					pHistory->Move( 0, &aHstr );
834cdf0e10cSrcweir 				}
835cdf0e10cSrcweir 				else
836cdf0e10cSrcweir 				{
837cdf0e10cSrcweir 					pHistory->Rollback( pDoc );
838cdf0e10cSrcweir 					DELETEZ( pHistory );
839cdf0e10cSrcweir 				}
840cdf0e10cSrcweir 			}
841cdf0e10cSrcweir 		}
842cdf0e10cSrcweir 
843cdf0e10cSrcweir 		if( bResetPgDesc || bResetPgBrk )
844cdf0e10cSrcweir 		{
845cdf0e10cSrcweir             sal_uInt16 nStt = static_cast<sal_uInt16>( bResetPgDesc ? RES_PAGEDESC : RES_BREAK );
846cdf0e10cSrcweir             sal_uInt16 nEnd = static_cast<sal_uInt16>( bResetPgBrk ? RES_BREAK : RES_PAGEDESC );
847cdf0e10cSrcweir 
848cdf0e10cSrcweir 			SwNode* pNode = pDoc->GetNodes()[ nEndNode + 1 ];
849cdf0e10cSrcweir 			if( pNode->IsCntntNode() )
850cdf0e10cSrcweir 				((SwCntntNode*)pNode)->ResetAttr( nStt, nEnd );
851cdf0e10cSrcweir 			else if( pNode->IsTableNode() )
852cdf0e10cSrcweir                 ((SwTableNode*)pNode)->GetTable().GetFrmFmt()->ResetFmtAttr( nStt, nEnd );
853cdf0e10cSrcweir 		}
854cdf0e10cSrcweir 	}
855cdf0e10cSrcweir 	// den temp. eingefuegten Node noch loeschen !!
856cdf0e10cSrcweir 	if( pInsNd )
857cdf0e10cSrcweir 		pDoc->GetNodes().Delete( aIdx, 1 );
858cdf0e10cSrcweir 	if( pRedlSaveData )
859cdf0e10cSrcweir 		SetSaveData( *pDoc, *pRedlSaveData );
860cdf0e10cSrcweir 
861cdf0e10cSrcweir     AddUndoRedoPaM(rContext, true);
862cdf0e10cSrcweir }
863cdf0e10cSrcweir 
RedoImpl(::sw::UndoRedoContext & rContext)864cdf0e10cSrcweir void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
865cdf0e10cSrcweir {
866cdf0e10cSrcweir     SwPaM & rPam = AddUndoRedoPaM(rContext);
867cdf0e10cSrcweir     SwDoc& rDoc = *rPam.GetDoc();
868cdf0e10cSrcweir 
869cdf0e10cSrcweir     if( pRedlSaveData )
870cdf0e10cSrcweir     {
871cdf0e10cSrcweir         bool bSuccess = FillSaveData(rPam, *pRedlSaveData, sal_True);
872cdf0e10cSrcweir         OSL_ENSURE(bSuccess,
873cdf0e10cSrcweir             "SwUndoDelete::Redo: used to have redline data, but now none?");
874cdf0e10cSrcweir         if (!bSuccess)
875cdf0e10cSrcweir         {
876cdf0e10cSrcweir             delete pRedlSaveData, pRedlSaveData = 0;
877cdf0e10cSrcweir         }
878cdf0e10cSrcweir     }
879cdf0e10cSrcweir 
880cdf0e10cSrcweir     if( !bDelFullPara )
881cdf0e10cSrcweir     {
882cdf0e10cSrcweir         SwUndRng aTmpRng( rPam );
883cdf0e10cSrcweir         RemoveIdxFromRange( rPam, sal_False );
884cdf0e10cSrcweir         aTmpRng.SetPaM( rPam );
885cdf0e10cSrcweir 
886cdf0e10cSrcweir         if( !bJoinNext )            // Dann Selektion von unten nach oben
887cdf0e10cSrcweir             rPam.Exchange();        // wieder herstellen!
888cdf0e10cSrcweir     }
889cdf0e10cSrcweir 
890cdf0e10cSrcweir     if( pHistory )      // wurden Attribute gesichert ?
891cdf0e10cSrcweir     {
892cdf0e10cSrcweir         pHistory->SetTmpEnd( pHistory->Count() );
893cdf0e10cSrcweir         SwHistory aHstr;
894cdf0e10cSrcweir         aHstr.Move( 0, pHistory );
895cdf0e10cSrcweir 
896cdf0e10cSrcweir         if( bDelFullPara )
897cdf0e10cSrcweir         {
898cdf0e10cSrcweir             ASSERT( rPam.HasMark(), "PaM ohne Mark" );
899cdf0e10cSrcweir             DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
900cdf0e10cSrcweir                             DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
901cdf0e10cSrcweir 
902cdf0e10cSrcweir             _DelBookmarks(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
903cdf0e10cSrcweir         }
904cdf0e10cSrcweir         else
905cdf0e10cSrcweir             DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
906cdf0e10cSrcweir         nSetPos = pHistory ? pHistory->Count() : 0;
907cdf0e10cSrcweir 
908cdf0e10cSrcweir         pHistory->Move( nSetPos, &aHstr );
909cdf0e10cSrcweir     }
910cdf0e10cSrcweir     else
911cdf0e10cSrcweir     {
912cdf0e10cSrcweir         if( bDelFullPara )
913cdf0e10cSrcweir         {
914cdf0e10cSrcweir             ASSERT( rPam.HasMark(), "PaM ohne Mark" );
915cdf0e10cSrcweir             DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
916cdf0e10cSrcweir                             DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
917cdf0e10cSrcweir 
918cdf0e10cSrcweir             _DelBookmarks( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
919cdf0e10cSrcweir         }
920cdf0e10cSrcweir         else
921cdf0e10cSrcweir             DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
922cdf0e10cSrcweir         nSetPos = pHistory ? pHistory->Count() : 0;
923cdf0e10cSrcweir     }
924cdf0e10cSrcweir 
925cdf0e10cSrcweir     if( !pSttStr && !pEndStr )
926cdf0e10cSrcweir     {
927cdf0e10cSrcweir         SwNodeIndex aSttIdx = ( bDelFullPara || bJoinNext )
928cdf0e10cSrcweir                                     ? rPam.GetMark()->nNode
929cdf0e10cSrcweir                                     : rPam.GetPoint()->nNode;
930cdf0e10cSrcweir         SwTableNode* pTblNd = aSttIdx.GetNode().GetTableNode();
931cdf0e10cSrcweir         if( pTblNd )
932cdf0e10cSrcweir         {
933cdf0e10cSrcweir             if( bTblDelLastNd )
934cdf0e10cSrcweir             {
935cdf0e10cSrcweir                 // dann am Ende wieder einen Node einfuegen
936cdf0e10cSrcweir                 const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
937cdf0e10cSrcweir                 rDoc.GetNodes().MakeTxtNode( aTmpIdx,
938cdf0e10cSrcweir                         rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
939cdf0e10cSrcweir             }
940cdf0e10cSrcweir 
941cdf0e10cSrcweir             SwCntntNode* pNextNd = rDoc.GetNodes()[
942cdf0e10cSrcweir                     pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
943cdf0e10cSrcweir             if( pNextNd )
944cdf0e10cSrcweir             {
945cdf0e10cSrcweir                 SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
946cdf0e10cSrcweir 
947cdf0e10cSrcweir                 const SfxPoolItem *pItem;
948cdf0e10cSrcweir                 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
949cdf0e10cSrcweir                     sal_False, &pItem ) )
950cdf0e10cSrcweir                     pNextNd->SetAttr( *pItem );
951cdf0e10cSrcweir 
952cdf0e10cSrcweir                 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
953cdf0e10cSrcweir                     sal_False, &pItem ) )
954cdf0e10cSrcweir                     pNextNd->SetAttr( *pItem );
955cdf0e10cSrcweir             }
956cdf0e10cSrcweir             pTblNd->DelFrms();
957cdf0e10cSrcweir         }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir         rPam.SetMark();
960cdf0e10cSrcweir         rPam.DeleteMark();
961cdf0e10cSrcweir 
962cdf0e10cSrcweir         rDoc.GetNodes().Delete( aSttIdx, nEndNode - nSttNode );
963cdf0e10cSrcweir 
964cdf0e10cSrcweir         // setze den Cursor immer in einen ContentNode !!
965cdf0e10cSrcweir         if( !rPam.Move( fnMoveBackward, fnGoCntnt ) &&
966cdf0e10cSrcweir             !rPam.Move( fnMoveForward, fnGoCntnt ) )
967cdf0e10cSrcweir             rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
968cdf0e10cSrcweir     }
969cdf0e10cSrcweir     else if( bDelFullPara )
970cdf0e10cSrcweir     {
971cdf0e10cSrcweir         // der Pam wurde am Point( == Ende) um eins erhoeht, um einen
972cdf0e10cSrcweir         // Bereich fuers Undo zu haben. Der muss jetzt aber wieder entfernt
973cdf0e10cSrcweir         // werden!!!
974cdf0e10cSrcweir         rPam.End()->nNode--;
975cdf0e10cSrcweir         if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
976cdf0e10cSrcweir             *rPam.GetMark() = *rPam.GetPoint();
977cdf0e10cSrcweir         rDoc.DelFullPara( rPam );
978cdf0e10cSrcweir     }
979cdf0e10cSrcweir     else
980cdf0e10cSrcweir         rDoc.DeleteAndJoin( rPam );
981cdf0e10cSrcweir }
982cdf0e10cSrcweir 
RepeatImpl(::sw::RepeatContext & rContext)983cdf0e10cSrcweir void SwUndoDelete::RepeatImpl(::sw::RepeatContext & rContext)
984cdf0e10cSrcweir {
985cdf0e10cSrcweir     // this action does not seem idempotent,
986cdf0e10cSrcweir     // so make sure it is only executed once on repeat
987cdf0e10cSrcweir     if (rContext.m_bDeleteRepeated)
988cdf0e10cSrcweir 		return;
989cdf0e10cSrcweir 
990cdf0e10cSrcweir     SwPaM & rPam = rContext.GetRepeatPaM();
991cdf0e10cSrcweir 	SwDoc& rDoc = *rPam.GetDoc();
992cdf0e10cSrcweir     ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
993cdf0e10cSrcweir 	if( !rPam.HasMark() )
994cdf0e10cSrcweir 	{
995cdf0e10cSrcweir 		rPam.SetMark();
996cdf0e10cSrcweir 		rPam.Move( fnMoveForward, fnGoCntnt );
997cdf0e10cSrcweir 	}
998cdf0e10cSrcweir 	if( bDelFullPara )
999cdf0e10cSrcweir 		rDoc.DelFullPara( rPam );
1000cdf0e10cSrcweir 	else
1001cdf0e10cSrcweir 		rDoc.DeleteAndJoin( rPam );
1002cdf0e10cSrcweir     rContext.m_bDeleteRepeated = true;
1003cdf0e10cSrcweir }
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 
SetTableName(const String & rName)1006cdf0e10cSrcweir void SwUndoDelete::SetTableName(const String & rName)
1007cdf0e10cSrcweir {
1008cdf0e10cSrcweir     sTableName = rName;
1009cdf0e10cSrcweir }
1010