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
10cdf0e10cSrcweir *
11efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
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.
19cdf0e10cSrcweir *
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