Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <UndoDelete.hxx>
30 : : #include <hintids.hxx>
31 : : #include <unotools/charclass.hxx>
32 : : #include <editeng/brkitem.hxx>
33 : : #include <fmtpdsc.hxx>
34 : : #include <frmfmt.hxx>
35 : : #include <fmtanchr.hxx>
36 : : #include <doc.hxx>
37 : : #include <UndoManager.hxx>
38 : : #include <swtable.hxx>
39 : : #include <swundo.hxx>
40 : : #include <pam.hxx>
41 : : #include <ndtxt.hxx>
42 : : #include <UndoCore.hxx>
43 : : #include <rolbck.hxx>
44 : : #include <poolfmt.hxx>
45 : : #include <mvsave.hxx>
46 : : #include <redline.hxx>
47 : : #include <docary.hxx>
48 : : #include <sfx2/app.hxx>
49 : : #include <fldbas.hxx>
50 : : #include <fmtfld.hxx>
51 : : #include <comcore.hrc> // #111827#
52 : : #include <undo.hrc>
53 : : #include <vector>
54 : :
55 : : // DELETE
56 : : /* lcl_MakeAutoFrms has to call MakeFrms for objects bounded "AtChar"
57 : : ( == AUTO ), if the anchor frame has be moved via _MoveNodes(..) and
58 : : DelFrms(..)
59 : : */
60 : 0 : void lcl_MakeAutoFrms( const SwFrmFmts& rSpzArr, sal_uLong nMovedIndex )
61 : : {
62 [ # # ]: 0 : if( !rSpzArr.empty() )
63 : : {
64 : : SwFlyFrmFmt* pFmt;
65 : : const SwFmtAnchor* pAnchor;
66 [ # # ]: 0 : for( sal_uInt16 n = 0; n < rSpzArr.size(); ++n )
67 : : {
68 : 0 : pFmt = (SwFlyFrmFmt*)rSpzArr[n];
69 : 0 : pAnchor = &pFmt->GetAnchor();
70 [ # # ]: 0 : if (pAnchor->GetAnchorId() == FLY_AT_CHAR)
71 : : {
72 : 0 : const SwPosition* pAPos = pAnchor->GetCntntAnchor();
73 [ # # ][ # # ]: 0 : if( pAPos && nMovedIndex == pAPos->nNode.GetIndex() )
[ # # ]
74 : 0 : pFmt->MakeFrms();
75 : : }
76 : : }
77 : : }
78 : 0 : }
79 : :
80 : : // SwUndoDelete has to perform a deletion and to record anything that is needed
81 : : // to restore the situation before the deletion. Unfortunately a part of the
82 : : // deletion will be done after calling this Ctor, this has to be kept in mind!
83 : : // In this Ctor only the complete paragraphs will be deleted, the joining of
84 : : // the first and last paragraph of the selection will be handled outside this
85 : : // function.
86 : : // Here are the main steps of the function:
87 : : // 1. Deletion/recording of content indizes of the selection: footnotes, fly
88 : : // frames and bookmarks
89 : : // Step 1 could shift all nodes by deletion of footnotes => nNdDiff will be set.
90 : : // 2. If the paragraph where the selection ends, is the last content of a
91 : : // section so that this section becomes empty when the paragraphs will be
92 : : // joined we have to do some smart actions ;-) The paragraph will be moved
93 : : // outside the section and replaced by a dummy text node, the complete
94 : : // section will be deleted in step 3. The difference between replacement
95 : : // dummy and original is nReplacementDummy.
96 : : // 3. Moving complete selected nodes into the UndoArray. Before this happens the
97 : : // selection has to be extended if there are sections which would become
98 : : // empty otherwise. BTW: sections will be moved into the UndoArray if they
99 : : // are complete part of the selection. Sections starting or ending outside
100 : : // of the selection will not be removed from the DocNodeArray even they got
101 : : // a "dummy"-copy in the UndoArray.
102 : : // 4. We have to anticipate the joining of the two paragraphs if the start
103 : : // paragraph is inside a section and the end paragraph not. Then we have to
104 : : // move the paragraph into this section and to record this in nSectDiff.
105 : 966 : SwUndoDelete::SwUndoDelete( SwPaM& rPam, sal_Bool bFullPara, sal_Bool bCalledByTblCpy )
106 : : : SwUndo(UNDO_DELETE), SwUndRng( rPam ),
107 : : pMvStt( 0 ), pSttStr(0), pEndStr(0), pRedlData(0), pRedlSaveData(0),
108 : : nNode(0), nNdDiff(0), nSectDiff(0), nReplaceDummy(0), nSetPos(0),
109 : : bGroup( sal_False ), bBackSp( sal_False ), bJoinNext( sal_False ), bTblDelLastNd( sal_False ),
110 : : bDelFullPara( bFullPara ), bResetPgDesc( sal_False ), bResetPgBrk( sal_False ),
111 [ + - ][ + - ]: 966 : bFromTableCopy( bCalledByTblCpy )
[ + - ][ + - ]
[ + - ]
112 : : {
113 : : // bFullPara is set e.g. if an empty paragraph before a table is deleted
114 : 966 : bDelFullPara = bFullPara;
115 : :
116 : 966 : bCacheComment = false;
117 : :
118 : 966 : SwDoc * pDoc = rPam.GetDoc();
119 : :
120 [ + - ][ + - ]: 966 : if( !pDoc->IsIgnoreRedline() && !pDoc->GetRedlineTbl().empty() )
[ - + ][ - + ]
[ + - ]
121 : : {
122 [ # # ][ # # ]: 0 : pRedlSaveData = new SwRedlineSaveDatas;
123 [ # # ][ # # ]: 0 : if( !FillSaveData( rPam, *pRedlSaveData ))
124 [ # # ][ # # ]: 0 : delete pRedlSaveData, pRedlSaveData = 0;
125 : : }
126 : :
127 [ + - ]: 966 : if( !pHistory )
128 [ + - ][ + - ]: 966 : pHistory = new SwHistory;
129 : :
130 : : // delete all footnotes for now
131 [ + - ]: 966 : const SwPosition *pStt = rPam.Start(),
132 : 966 : *pEnd = rPam.GetPoint() == pStt
133 : : ? rPam.GetMark()
134 [ + + ]: 966 : : rPam.GetPoint();
135 : :
136 : : // Step 1. deletion/record of content indizes
137 [ - + ]: 966 : if( bDelFullPara )
138 : : {
139 : : OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
140 : 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
141 [ # # ]: 0 : DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
142 : :
143 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
144 [ # # ][ # # ]: 0 : _DelBookmarks(pStt->nNode, pEnd->nNode);
145 : : }
146 : : else
147 [ + - ]: 966 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
148 : :
149 [ + - ]: 966 : nSetPos = pHistory ? pHistory->Count() : 0;
150 : :
151 : : // Is already anything deleted?
152 : 966 : nNdDiff = nSttNode - pStt->nNode.GetIndex();
153 : :
154 [ + + ][ + - ]: 966 : bJoinNext = !bFullPara && pEnd == rPam.GetPoint();
155 [ + - ][ + + ]: 966 : bBackSp = !bFullPara && !bJoinNext;
156 : :
157 : 966 : SwTxtNode *pSttTxtNd = 0, *pEndTxtNd = 0;
158 [ + - ]: 966 : if( !bFullPara )
159 : : {
160 : 966 : pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
161 : : pEndTxtNd = nSttNode == nEndNode
162 : : ? pSttTxtNd
163 [ + + ]: 966 : : pEnd->nNode.GetNode().GetTxtNode();
164 : : }
165 : :
166 [ + - ]: 966 : sal_Bool bMoveNds = *pStt == *pEnd // any area still existent?
167 : : ? sal_False
168 [ + + ][ + - ]: 966 : : ( SaveCntnt( pStt, pEnd, pSttTxtNd, pEndTxtNd ) || bFromTableCopy );
[ + + ][ - + ]
169 : :
170 [ + + ][ + - ]: 966 : if( pSttTxtNd && pEndTxtNd && pSttTxtNd != pEndTxtNd )
[ + + ]
171 : : {
172 : : // two different TextNodes, thus save also the TextFormatCollection
173 [ + - ]: 26 : pHistory->Add( pSttTxtNd->GetTxtColl(),pStt->nNode.GetIndex(), ND_TEXTNODE );
174 [ + - ]: 26 : pHistory->Add( pEndTxtNd->GetTxtColl(),pEnd->nNode.GetIndex(), ND_TEXTNODE );
175 : :
176 [ - + ]: 26 : if( !bJoinNext ) // Selection from bottom to top
177 : : {
178 : : // When using JoinPrev() all AUTO-PageBreak's will be copied
179 : : // correctly. To restore them with UNDO, Auto-PageBreak of the
180 : : // EndNode needs to be reset. Same for PageDesc and ColBreak.
181 [ # # ][ # # ]: 0 : if( pEndTxtNd->HasSwAttrSet() )
182 : : {
183 [ # # ]: 0 : SwRegHistory aRegHist( *pEndTxtNd, pHistory );
184 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
185 [ # # ]: 0 : RES_BREAK, sal_False ) )
186 [ # # ]: 0 : pEndTxtNd->ResetAttr( RES_BREAK );
187 [ # # ][ # # ]: 0 : if( pEndTxtNd->HasSwAttrSet() &&
[ # # ][ # # ]
188 [ # # ]: 0 : SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
189 [ # # ]: 0 : RES_PAGEDESC, sal_False ) )
190 [ # # ][ # # ]: 0 : pEndTxtNd->ResetAttr( RES_PAGEDESC );
191 : : }
192 : : }
193 : : }
194 : :
195 : : // Move now also the PaM. The SPoint is at the beginning of a SSelection.
196 [ + + ][ - + ]: 966 : if( pEnd == rPam.GetPoint() && ( !bFullPara || pSttTxtNd || pEndTxtNd ) )
[ # # ][ # # ]
[ + + ]
197 : 894 : rPam.Exchange();
198 : :
199 [ + + ][ + - ]: 966 : if( !pSttTxtNd && !pEndTxtNd )
200 [ + - ]: 10 : rPam.GetPoint()->nNode--;
201 [ + - ]: 966 : rPam.DeleteMark(); // the SPoint is in the selection
202 : :
203 [ + + ]: 966 : if( !pEndTxtNd )
204 : 10 : nEndCntnt = 0;
205 [ + + ]: 966 : if( !pSttTxtNd )
206 : 10 : nSttCntnt = 0;
207 : :
208 [ + + ]: 966 : if( bMoveNds ) // Do Nodes exist that need to be moved?
209 : : {
210 [ + - ][ + - ]: 16 : SwNodes& rNds = pDoc->GetUndoManager().GetUndoNodes();
211 [ + - ]: 16 : SwNodes& rDocNds = pDoc->GetNodes();
212 : : SwNodeRange aRg( rDocNds, nSttNode - nNdDiff,
213 [ + - ][ + - ]: 16 : rDocNds, nEndNode - nNdDiff );
[ + - ][ + - ]
[ + - ]
214 [ + - ]: 26 : if( !bFullPara && !pEndTxtNd &&
[ + + + - ]
[ + + ]
215 [ + - ]: 10 : &aRg.aEnd.GetNode() != &pDoc->GetNodes().GetEndOfContent() )
216 : : {
217 : 10 : SwNode* pNode = aRg.aEnd.GetNode().StartOfSectionNode();
218 [ + - ]: 10 : if( pNode->GetIndex() >= nSttNode - nNdDiff )
219 [ + - ]: 10 : aRg.aEnd++; // Deletion of a complete table
220 : : }
221 : : SwNode* pTmpNd;
222 : : // Step 2: Expand selection if necessary
223 [ + + ][ - + ]: 16 : if( bJoinNext || bFullPara )
224 : : {
225 : : // If all content of a section will be moved into Undo, the section
226 : : // itself should be moved completely.
227 [ - + # # : 6 : while( aRg.aEnd.GetIndex() + 2 < rDocNds.Count() &&
# # # # #
# ][ - + ]
228 : 0 : ( (pTmpNd = rDocNds[ aRg.aEnd.GetIndex()+1 ])->IsEndNode() &&
229 : 0 : pTmpNd->StartOfSectionNode()->IsSectionNode() &&
230 : 0 : pTmpNd->StartOfSectionNode()->GetIndex() >= aRg.aStart.GetIndex() ) )
231 [ # # ]: 0 : aRg.aEnd++;
232 : 6 : nReplaceDummy = aRg.aEnd.GetIndex() + nNdDiff - nEndNode;
233 [ - + ]: 6 : if( nReplaceDummy )
234 : : { // The selection has been expanded, because
235 [ # # ]: 0 : aRg.aEnd++;
236 [ # # ]: 0 : if( pEndTxtNd )
237 : : {
238 : : // The end text node has to leave the (expanded) selection
239 : : // The dummy is needed because _MoveNodes deletes empty
240 : : // sections
241 : 0 : ++nReplaceDummy;
242 [ # # ]: 0 : SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
243 [ # # ]: 0 : SwPosition aSplitPos( *pEndTxtNd );
244 [ # # ][ # # ]: 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
245 [ # # ]: 0 : pDoc->SplitNode( aSplitPos, false );
246 [ # # ]: 0 : rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
247 [ # # ][ # # ]: 0 : aRg.aEnd--;
[ # # ][ # # ]
248 : : }
249 : : else
250 : 0 : nReplaceDummy = 0;
251 : : }
252 : : }
253 [ + + ][ - + ]: 16 : if( bBackSp || bFullPara )
254 : : {
255 : : // See above, the selection has to be expanded if there are "nearly
256 : : // empty" sections and a replacement dummy has to be set if needed.
257 [ + - + - : 30 : while( 1 < aRg.aStart.GetIndex() &&
- + # # ]
[ - + ]
258 : 20 : ( (pTmpNd = rDocNds[ aRg.aStart.GetIndex()-1 ])->IsSectionNode() &&
259 : 0 : pTmpNd->EndOfSectionIndex() < aRg.aEnd.GetIndex() ) )
260 [ # # ]: 0 : aRg.aStart--;
261 [ - + ]: 10 : if( pSttTxtNd )
262 : : {
263 : 0 : nReplaceDummy = nSttNode - nNdDiff - aRg.aStart.GetIndex();
264 [ # # ]: 0 : if( nReplaceDummy )
265 : : {
266 [ # # ]: 0 : SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
267 [ # # ]: 0 : SwPosition aSplitPos( *pSttTxtNd );
268 [ # # ][ # # ]: 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
269 [ # # ]: 0 : pDoc->SplitNode( aSplitPos, false );
270 [ # # ]: 0 : rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
271 [ # # ][ # # ]: 0 : aRg.aStart--;
[ # # ][ # # ]
272 : : }
273 : : }
274 : : }
275 : :
276 [ - + ]: 16 : if( bFromTableCopy )
277 : : {
278 [ # # ]: 0 : if( !pEndTxtNd )
279 : : {
280 [ # # ]: 0 : if( pSttTxtNd )
281 [ # # ]: 0 : aRg.aStart++;
282 [ # # ][ # # ]: 0 : else if( !bFullPara && !aRg.aEnd.GetNode().IsCntntNode() )
[ # # ]
283 [ # # ]: 0 : aRg.aEnd--;
284 : : }
285 : : }
286 [ + + ][ - + ]: 16 : else if( pSttTxtNd && ( pEndTxtNd || pSttTxtNd->GetTxt().Len() ) )
[ # # ][ + + ]
287 [ + - ]: 6 : aRg.aStart++;
288 : :
289 : : // Step 3: Moving into UndoArray...
290 : 16 : nNode = rNds.GetEndOfContent().GetIndex();
291 [ + - ][ + - ]: 16 : rDocNds._MoveNodes( aRg, rNds, SwNodeIndex( rNds.GetEndOfContent() ));
[ + - ]
292 [ + - ][ + - ]: 16 : pMvStt = new SwNodeIndex( rNds, nNode );
293 : : // remember difference!
294 : 16 : nNode = rNds.GetEndOfContent().GetIndex() - nNode;
295 : :
296 [ + - ][ + + ]: 16 : if( pSttTxtNd && pEndTxtNd )
297 : : {
298 : : //Step 4: Moving around sections
299 : 6 : nSectDiff = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
300 : : // nSect is the number of sections which starts(ends) between start
301 : : // and end node of the selection. The "loser" paragraph has to be
302 : : // moved into the section(s) of the "winner" paragraph
303 [ - + ]: 6 : if( nSectDiff )
304 : : {
305 [ # # ]: 0 : if( bJoinNext )
306 : : {
307 [ # # ]: 0 : SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
308 [ # # ][ # # ]: 0 : rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
309 : : }
310 : : else
311 : : {
312 [ # # ]: 0 : SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
313 [ # # ][ # # ]: 0 : rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
314 : : }
315 : : }
316 : : }
317 [ + - ][ - + ]: 16 : if( nSectDiff || nReplaceDummy )
318 : 0 : lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(),
319 [ # # ][ # # ]: 16 : bJoinNext ? pEndTxtNd->GetIndex() : pSttTxtNd->GetIndex() );
[ + - ]
320 : : }
321 : : else
322 : 950 : nNode = 0; // moved no node -> no difference at the end
323 : :
324 : : // Are there any Nodes that got deleted before that (FootNotes
325 : : // have ContentNodes)?
326 [ + + ][ + - ]: 966 : if( !pSttTxtNd && !pEndTxtNd )
327 : : {
328 : 10 : nNdDiff = nSttNode - rPam.GetPoint()->nNode.GetIndex() - (bFullPara ? 0 : 1);
329 [ + - ]: 10 : rPam.Move( fnMoveForward, fnGoNode );
330 : : }
331 : : else
332 : : {
333 : 956 : nNdDiff = nSttNode;
334 [ - + ][ # # ]: 956 : if( nSectDiff && bBackSp )
335 : 0 : nNdDiff += nSectDiff;
336 : 956 : nNdDiff -= rPam.GetPoint()->nNode.GetIndex();
337 : : }
338 : :
339 [ - + ]: 966 : if( !rPam.GetNode()->IsCntntNode() )
340 [ # # ]: 0 : rPam.GetPoint()->nContent.Assign( 0, 0 );
341 : :
342 : : // is a history necessary here at all?
343 [ + - ][ + + ]: 966 : if( pHistory && !pHistory->Count() )
[ + + ]
344 [ + - ][ + - ]: 616 : DELETEZ( pHistory );
345 : 966 : }
346 : :
347 : 956 : sal_Bool SwUndoDelete::SaveCntnt( const SwPosition* pStt, const SwPosition* pEnd,
348 : : SwTxtNode* pSttTxtNd, SwTxtNode* pEndTxtNd )
349 : : {
350 : 956 : sal_uLong nNdIdx = pStt->nNode.GetIndex();
351 : : // 1 - copy start in Start-String
352 [ + + ]: 956 : if( pSttTxtNd )
353 : : {
354 : 946 : sal_Bool bOneNode = nSttNode == nEndNode;
355 : : xub_StrLen nLen = bOneNode ? nEndCntnt - nSttCntnt
356 [ + + ]: 946 : : pSttTxtNd->GetTxt().Len() - nSttCntnt;
357 [ + - ]: 946 : SwRegHistory aRHst( *pSttTxtNd, pHistory );
358 : : // always save all text atttibutes because of possibly overlapping
359 : : // areas of on/off
360 : : pHistory->CopyAttr( pSttTxtNd->GetpSwpHints(), nNdIdx,
361 [ + - ]: 946 : 0, pSttTxtNd->GetTxt().Len(), true );
362 [ + + ][ + - ]: 946 : if( !bOneNode && pSttTxtNd->HasSwAttrSet() )
[ + + ][ + + ]
363 [ + - ][ + - ]: 12 : pHistory->CopyFmtAttr( *pSttTxtNd->GetpSwAttrSet(), nNdIdx );
364 : :
365 : : // the length might have changed (!!Fields!!)
366 : 26 : nLen = ( bOneNode ? pEnd->nContent.GetIndex() : pSttTxtNd->GetTxt().Len() )
367 [ + + ]: 972 : - pStt->nContent.GetIndex();
368 : :
369 : : // delete now also the text (all attribute changes are added to
370 : : // UNDO history)
371 [ + - ][ + - ]: 946 : pSttStr = (String*)new String( pSttTxtNd->GetTxt().Copy( nSttCntnt, nLen ));
372 [ + - ]: 946 : pSttTxtNd->EraseText( pStt->nContent, nLen );
373 [ + + ]: 946 : if( pSttTxtNd->GetpSwpHints() )
374 : 66 : pSttTxtNd->GetpSwpHints()->DeRegister();
375 : :
376 : : // METADATA: store
377 [ + + ][ + - ]: 946 : bool emptied( pSttStr->Len() && !pSttTxtNd->Len() );
[ + + ]
378 [ + + ][ + + ]: 946 : if (!bOneNode || emptied) // merging may overwrite xmlids...
379 : : {
380 : : m_pMetadataUndoStart = (emptied)
381 : : ? pSttTxtNd->CreateUndoForDelete()
382 [ + + ][ + - ]: 176 : : pSttTxtNd->CreateUndo();
[ + - ][ + - ]
[ + - ]
383 : : }
384 : :
385 [ + + ]: 946 : if( bOneNode )
386 [ + - ][ + + ]: 946 : return sal_False; // stop moving more nodes
387 : : }
388 : :
389 : : // 2 - copy end into End-String
390 [ + + ]: 36 : if( pEndTxtNd )
391 : : {
392 [ + - ][ + - ]: 26 : SwIndex aEndIdx( pEndTxtNd );
393 : 26 : nNdIdx = pEnd->nNode.GetIndex();
394 [ + - ]: 26 : SwRegHistory aRHst( *pEndTxtNd, pHistory );
395 : :
396 : : // always save all text atttibutes because of possibly overlapping
397 : : // areas of on/off
398 : : pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nNdIdx, 0,
399 [ + - ]: 26 : pEndTxtNd->GetTxt().Len(), true );
400 : :
401 [ + - ][ + + ]: 26 : if( pEndTxtNd->HasSwAttrSet() )
402 [ + - ][ + - ]: 10 : pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nNdIdx );
403 : :
404 : : // delete now also the text (all attribute changes are added to
405 : : // UNDO history)
406 : : pEndStr = (String*)new String( pEndTxtNd->GetTxt().Copy( 0,
407 [ + - ][ + - ]: 26 : pEnd->nContent.GetIndex() ));
408 [ + - ]: 26 : pEndTxtNd->EraseText( aEndIdx, pEnd->nContent.GetIndex() );
409 [ - + ]: 26 : if( pEndTxtNd->GetpSwpHints() )
410 : 0 : pEndTxtNd->GetpSwpHints()->DeRegister();
411 : :
412 : : // METADATA: store
413 [ + + ][ + - ]: 26 : bool emptied( pEndStr->Len() && !pEndTxtNd->Len() );
[ + + ]
414 : :
415 : : m_pMetadataUndoEnd = (emptied)
416 : : ? pEndTxtNd->CreateUndoForDelete()
417 [ + + ][ + - ]: 26 : : pEndTxtNd->CreateUndo();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
418 : : }
419 : :
420 : : // if there are only two Nodes than we're done
421 [ + + ][ - + ]: 36 : if( ( pSttTxtNd || pEndTxtNd ) && nSttNode + 1 == nEndNode )
[ + + ]
422 : 20 : return sal_False; // do not move any Node
423 : :
424 : 956 : return sal_True; // move Nodes lying in between
425 : : }
426 : :
427 : 0 : sal_Bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
428 : : {
429 : : // Is Undo greater than one Node (that is Start and EndString)?
430 [ # # ][ # # ]: 0 : if( pSttStr ? !pSttStr->Len() || pEndStr : sal_True )
[ # # ][ # # ]
431 : 0 : return sal_False;
432 : :
433 : : // only the deletion of single char's can be condensed
434 [ # # ][ # # ]: 0 : if( nSttNode != nEndNode || ( !bGroup && nSttCntnt+1 != nEndCntnt ))
[ # # ]
435 : 0 : return sal_False;
436 : :
437 : 0 : const SwPosition *pStt = rDelPam.Start(),
438 : 0 : *pEnd = rDelPam.GetPoint() == pStt
439 : : ? rDelPam.GetMark()
440 [ # # ]: 0 : : rDelPam.GetPoint();
441 : :
442 [ # # # # : 0 : if( pStt->nNode != pEnd->nNode ||
# # ][ # # ]
443 : 0 : pStt->nContent.GetIndex()+1 != pEnd->nContent.GetIndex() ||
444 : 0 : pEnd->nNode != nSttNode )
445 : 0 : return sal_False;
446 : :
447 : : // Distinguish between BackSpace and Delete because the Undo array needs to
448 : : // be constructed differently!
449 [ # # ]: 0 : if( pEnd->nContent == nSttCntnt )
450 : : {
451 [ # # ][ # # ]: 0 : if( bGroup && !bBackSp ) return sal_False;
452 : 0 : bBackSp = sal_True;
453 : : }
454 [ # # ]: 0 : else if( pStt->nContent == nSttCntnt )
455 : : {
456 [ # # ][ # # ]: 0 : if( bGroup && bBackSp ) return sal_False;
457 : 0 : bBackSp = sal_False;
458 : : }
459 : : else
460 : 0 : return sal_False;
461 : :
462 : : // are both Nodes (Node/Undo array) TextNodes at all?
463 : 0 : SwTxtNode * pDelTxtNd = pStt->nNode.GetNode().GetTxtNode();
464 [ # # ]: 0 : if( !pDelTxtNd ) return sal_False;
465 : :
466 [ # # ]: 0 : xub_StrLen nUChrPos = bBackSp ? 0 : pSttStr->Len()-1;
467 : 0 : sal_Unicode cDelChar = pDelTxtNd->GetTxt().GetChar( pStt->nContent.GetIndex() );
468 : 0 : CharClass& rCC = GetAppCharClass();
469 [ # # ][ # # ]: 0 : if( ( CH_TXTATR_BREAKWORD == cDelChar || CH_TXTATR_INWORD == cDelChar ) ||
[ # # ][ # # ]
470 [ # # ][ # # ]: 0 : rCC.isLetterNumeric( rtl::OUString( cDelChar ), 0 ) !=
[ # # ][ # # ]
[ # # ]
[ # # # # ]
471 [ # # ]: 0 : rCC.isLetterNumeric( *pSttStr, nUChrPos ) )
472 : 0 : return sal_False;
473 : :
474 : : {
475 [ # # ]: 0 : SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
476 [ # # ]: 0 : if( !FillSaveData( rDelPam, *pTmpSav, sal_False ))
477 [ # # ]: 0 : delete pTmpSav, pTmpSav = 0;
478 : :
479 : 0 : sal_Bool bOk = ( !pRedlSaveData && !pTmpSav ) ||
480 : : ( pRedlSaveData && pTmpSav &&
481 [ # # ][ # # ]: 0 : SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav, bBackSp ));
[ # # ][ # # ]
[ # # ]
482 [ # # ]: 0 : delete pTmpSav;
483 [ # # ]: 0 : if( !bOk )
484 : 0 : return sal_False;
485 : :
486 : 0 : pDoc->DeleteRedline( rDelPam, false, USHRT_MAX );
487 : : }
488 : :
489 : : // Both 'deletes' can be consolidated, so 'move' the related character
490 [ # # ]: 0 : if( bBackSp )
491 : 0 : nSttCntnt--; // BackSpace: add char to array!
492 : : else
493 : : {
494 : 0 : nEndCntnt++; // Delete: attach char at the end
495 : 0 : nUChrPos++;
496 : : }
497 : 0 : pSttStr->Insert( cDelChar, nUChrPos );
498 : 0 : pDelTxtNd->EraseText( pStt->nContent, 1 );
499 : :
500 : 0 : bGroup = sal_True;
501 : 0 : return sal_True;
502 : : }
503 : :
504 [ + - ][ + - ]: 952 : SwUndoDelete::~SwUndoDelete()
[ + - ][ + - ]
505 : : {
506 [ + + ][ + - ]: 952 : delete pSttStr;
507 [ + + ][ + - ]: 952 : delete pEndStr;
508 [ + + ]: 952 : if( pMvStt ) // Delete also the selection from UndoNodes array
509 : : {
510 : : // Insert saves content in IconSection
511 [ + - ]: 14 : pMvStt->GetNode().GetNodes().Delete( *pMvStt, nNode );
512 [ + - ][ + - ]: 14 : delete pMvStt;
513 : : }
514 [ - + ][ # # ]: 952 : delete pRedlData;
515 [ - + ][ # # ]: 952 : delete pRedlSaveData;
516 [ - + ]: 1904 : }
517 : :
518 : 346 : static SwRewriter lcl_RewriterFromHistory(SwHistory & rHistory)
519 : : {
520 : 346 : SwRewriter aRewriter;
521 : :
522 : 346 : bool bDone = false;
523 : :
524 [ + + ]: 1138 : for ( sal_uInt16 n = 0; n < rHistory.Count(); n++)
525 : : {
526 [ + - ][ + - ]: 792 : String aDescr = rHistory[n]->GetDescription();
527 : :
528 [ + + ]: 792 : if (aDescr.Len() > 0)
529 : : {
530 [ + - ]: 45 : aRewriter.AddRule(UndoArg2, aDescr);
531 : :
532 : 792 : bDone = true;
533 : : break;
534 : : }
535 [ + - ][ + + ]: 792 : }
536 : :
537 [ + + ]: 346 : if (! bDone)
538 : : {
539 [ + - ][ + - ]: 301 : aRewriter.AddRule(UndoArg2, SW_RESSTR(STR_FIELD));
[ + - ][ + - ]
540 : : }
541 : :
542 : 346 : return aRewriter;
543 : : }
544 : :
545 : 268217 : static bool lcl_IsSpecialCharacter(sal_Unicode nChar)
546 : : {
547 [ + + ]: 268217 : switch (nChar)
548 : : {
549 : : case CH_TXTATR_BREAKWORD:
550 : : case CH_TXTATR_INWORD:
551 : : case CH_TXTATR_TAB:
552 : : case CH_TXTATR_NEWLINE:
553 : 400 : return true;
554 : :
555 : : default:
556 : 267817 : break;
557 : : }
558 : :
559 : 268217 : return false;
560 : : }
561 : :
562 : : const char UNDO_ARG1[] = "$1";
563 : : const char UNDO_ARG2[] = "$2";
564 : : const char UNDO_ARG3[] = "$3";
565 : :
566 : 8316 : static String lcl_DenotedPortion(String rStr, xub_StrLen nStart,
567 : : xub_StrLen nEnd)
568 : : {
569 : 8316 : String aResult;
570 : :
571 [ + + ]: 8316 : if (nEnd - nStart > 0)
572 : : {
573 : 8258 : sal_Unicode cLast = rStr.GetChar(nEnd - 1);
574 [ + + ]: 8258 : if (lcl_IsSpecialCharacter(cLast))
575 : : {
576 [ - + + - ]: 155 : switch(cLast)
577 : : {
578 : : case CH_TXTATR_TAB:
579 [ # # ][ # # ]: 0 : aResult = SW_RESSTR(STR_UNDO_TABS);
580 : :
581 : 0 : break;
582 : : case CH_TXTATR_NEWLINE:
583 [ + - ][ + - ]: 65 : aResult = SW_RESSTR(STR_UNDO_NLS);
584 : :
585 : 65 : break;
586 : :
587 : : case CH_TXTATR_INWORD:
588 : : case CH_TXTATR_BREAKWORD:
589 [ + - ]: 90 : aResult = rtl::OUString(UNDO_ARG2);
590 : :
591 : 90 : break;
592 : :
593 : : }
594 [ + - ]: 155 : SwRewriter aRewriter;
595 : : aRewriter.AddRule(UndoArg1,
596 [ + - ][ + - ]: 155 : String::CreateFromInt32(nEnd - nStart));
[ + - ]
597 [ + - ][ + - ]: 155 : aResult = aRewriter.Apply(aResult);
[ + - ][ + - ]
598 : : }
599 : : else
600 : : {
601 [ + - ][ + - ]: 8103 : aResult = SW_RESSTR(STR_START_QUOTE);
602 [ + - ][ + - ]: 8103 : aResult += rStr.Copy(nStart, nEnd - nStart);
[ + - ]
603 [ + - ][ + - ]: 8103 : aResult += SW_RESSTR(STR_END_QUOTE);
604 : : }
605 : : }
606 : :
607 : 8316 : return aResult;
608 : : }
609 : :
610 : 8179 : String DenoteSpecialCharacters(const String & rStr)
611 : : {
612 : 8179 : String aResult;
613 : :
614 [ + + ]: 8179 : if (rStr.Len() > 0)
615 : : {
616 : 8083 : bool bStart = false;
617 : 8083 : xub_StrLen nStart = 0;
618 : 8083 : sal_Unicode cLast = 0;
619 : :
620 [ + + ]: 138146 : for (xub_StrLen i = 0; i < rStr.Len(); i++)
621 : : {
622 [ + + ]: 130063 : if (lcl_IsSpecialCharacter(rStr.GetChar(i)))
623 : : {
624 [ + + ]: 167 : if (cLast != rStr.GetChar(i))
625 : 155 : bStart = true;
626 : :
627 : : }
628 : : else
629 : : {
630 [ + + ]: 129896 : if (lcl_IsSpecialCharacter(cLast))
631 : 78 : bStart = true;
632 : : }
633 : :
634 [ + + ]: 130063 : if (bStart)
635 : : {
636 [ + - ][ + - ]: 233 : aResult += lcl_DenotedPortion(rStr, nStart, i);
[ + - ][ + - ]
[ + - ]
637 : :
638 : 233 : nStart = i;
639 : 233 : bStart = false;
640 : : }
641 : :
642 : 130063 : cLast = rStr.GetChar(i);
643 : : }
644 : :
645 [ + - ][ + - ]: 8083 : aResult += lcl_DenotedPortion(rStr, nStart, rStr.Len());
[ + - ][ + - ]
[ + - ]
646 : : }
647 : : else
648 [ + - ]: 96 : aResult = rtl::OUString(UNDO_ARG2);
649 : :
650 : 8179 : return aResult;
651 : : }
652 : :
653 : 974 : SwRewriter SwUndoDelete::GetRewriter() const
654 : : {
655 : 974 : SwRewriter aResult;
656 : 974 : String * pStr = NULL;
657 : :
658 [ + + ]: 974 : if (nNode != 0)
659 : : {
660 [ + + ]: 20 : if (sTableName.Len() > 0)
661 : : {
662 : :
663 [ + - ]: 12 : SwRewriter aRewriter;
664 [ + - ][ + - ]: 12 : aRewriter.AddRule(UndoArg1, SW_RESSTR(STR_START_QUOTE));
[ + - ][ + - ]
665 [ + - ]: 12 : aRewriter.AddRule(UndoArg2, sTableName);
666 [ + - ][ + - ]: 12 : aRewriter.AddRule(UndoArg3, SW_RESSTR(STR_END_QUOTE));
[ + - ][ + - ]
667 : :
668 [ + - ][ + - ]: 12 : String sTmp = aRewriter.Apply(SW_RES(STR_TABLE_NAME));
[ + - ]
669 [ + - ][ + - ]: 12 : aResult.AddRule(UndoArg1, sTmp);
[ + - ]
670 : : }
671 : : else
672 [ + - ][ + - ]: 8 : aResult.AddRule(UndoArg1, SW_RESSTR(STR_PARAGRAPHS));
[ + - ][ + - ]
673 : : }
674 : : else
675 : : {
676 [ + - ]: 954 : String aStr;
677 : :
678 [ + + ][ + + ]: 958 : if (pSttStr != NULL && pEndStr != NULL && pSttStr->Len() == 0 &&
[ + + - + ]
[ - + ]
679 : 4 : pEndStr->Len() == 0)
680 : : {
681 [ # # ][ # # ]: 0 : aStr = SW_RESSTR(STR_PARAGRAPH_UNDO);
682 : : }
683 : : else
684 : : {
685 [ + + ]: 954 : if (pSttStr != NULL)
686 : 942 : pStr = pSttStr;
687 [ - + ]: 12 : else if (pEndStr != NULL)
688 : 0 : pStr = pEndStr;
689 : :
690 [ + + ]: 954 : if (pStr != NULL)
691 : : {
692 [ + - ][ + - ]: 942 : aStr = DenoteSpecialCharacters(*pStr);
[ + - ]
693 : : }
694 : : else
695 : : {
696 [ + - ]: 12 : aStr = rtl::OUString(UNDO_ARG2);
697 : : }
698 : : }
699 : :
700 [ + - ][ + - ]: 954 : aStr = ShortenString(aStr, nUndoStringLength, String(SW_RES(STR_LDOTS)));
[ + - ][ + - ]
[ + - ]
701 [ + + ]: 954 : if (pHistory)
702 : : {
703 [ + - ]: 346 : SwRewriter aRewriter = lcl_RewriterFromHistory(*pHistory);
704 [ + - ][ + - ]: 346 : aStr = aRewriter.Apply(aStr);
[ + - ][ + - ]
705 : : }
706 : :
707 [ + - ][ + - ]: 954 : aResult.AddRule(UndoArg1, aStr);
708 : : }
709 : :
710 : 974 : return aResult;
711 : : }
712 : :
713 : : // Every object, anchored "AtCntnt" will be reanchored at rPos
714 : 0 : void lcl_ReAnchorAtCntntFlyFrames( const SwFrmFmts& rSpzArr, SwPosition &rPos, sal_uLong nOldIdx )
715 : : {
716 [ # # ]: 0 : if( !rSpzArr.empty() )
717 : : {
718 : : SwFlyFrmFmt* pFmt;
719 : : const SwFmtAnchor* pAnchor;
720 : : const SwPosition* pAPos;
721 [ # # ]: 0 : for( sal_uInt16 n = 0; n < rSpzArr.size(); ++n )
722 : : {
723 : 0 : pFmt = (SwFlyFrmFmt*)rSpzArr[n];
724 : 0 : pAnchor = &pFmt->GetAnchor();
725 [ # # ]: 0 : if (pAnchor->GetAnchorId() == FLY_AT_PARA)
726 : : {
727 : 0 : pAPos = pAnchor->GetCntntAnchor();
728 [ # # ][ # # ]: 0 : if( pAPos && nOldIdx == pAPos->nNode.GetIndex() )
[ # # ]
729 : : {
730 [ # # ]: 0 : SwFmtAnchor aAnch( *pAnchor );
731 [ # # ]: 0 : aAnch.SetAnchor( &rPos );
732 [ # # ][ # # ]: 0 : pFmt->SetFmtAttr( aAnch );
733 : : }
734 : : }
735 : : }
736 : : }
737 : 0 : }
738 : :
739 : 0 : void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
740 : : {
741 : 0 : SwDoc *const pDoc = & rContext.GetDoc();
742 : :
743 : 0 : sal_uLong nCalcStt = nSttNode - nNdDiff;
744 : :
745 [ # # ][ # # ]: 0 : if( nSectDiff && bBackSp )
746 : 0 : nCalcStt += nSectDiff;
747 : :
748 [ # # ][ # # ]: 0 : SwNodeIndex aIdx( pDoc->GetNodes(), nCalcStt );
749 : 0 : SwNode* pInsNd = &aIdx.GetNode();
750 : :
751 : : { // code block so that SwPosition is detached when deleting a Node
752 [ # # ]: 0 : SwPosition aPos( aIdx );
753 [ # # ]: 0 : if( !bDelFullPara )
754 : : {
755 [ # # ]: 0 : if( pInsNd->IsTableNode() )
756 : : {
757 [ # # ]: 0 : pInsNd = pDoc->GetNodes().MakeTxtNode( aIdx,
758 [ # # ][ # # ]: 0 : (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
759 [ # # ]: 0 : aIdx--;
760 [ # # ]: 0 : aPos.nNode = aIdx;
761 [ # # ][ # # ]: 0 : aPos.nContent.Assign( pInsNd->GetCntntNode(), nSttCntnt );
762 : : }
763 : : else
764 : : {
765 [ # # ]: 0 : if( pInsNd->IsCntntNode() )
766 [ # # ][ # # ]: 0 : aPos.nContent.Assign( (SwCntntNode*)pInsNd, nSttCntnt );
[ # # ][ # # ]
767 [ # # ]: 0 : if( !bTblDelLastNd )
768 : 0 : pInsNd = 0; // do not delete Node!
769 : : }
770 : : }
771 : : else
772 : 0 : pInsNd = 0; // do not delete Node!
773 : :
774 : 0 : sal_Bool bNodeMove = 0 != nNode;
775 : :
776 [ # # ]: 0 : if( pEndStr )
777 : : {
778 : : // discard attributes since they all saved!
779 : 0 : SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
780 : :
781 [ # # ][ # # ]: 0 : if( pTxtNd && pTxtNd->HasSwAttrSet() )
[ # # ][ # # ]
782 [ # # ]: 0 : pTxtNd->ResetAllAttr();
783 : :
784 [ # # ][ # # ]: 0 : if( pTxtNd && pTxtNd->GetpSwpHints() )
[ # # ]
785 [ # # ]: 0 : pTxtNd->ClearSwpHintsArr( true );
786 : :
787 [ # # ][ # # ]: 0 : if( pSttStr && !bFromTableCopy )
788 : : {
789 : 0 : sal_uLong nOldIdx = aPos.nNode.GetIndex();
790 [ # # ]: 0 : pDoc->SplitNode( aPos, false );
791 : : // After the split all objects are anchored at the first
792 : : // paragraph, but the pHistory of the fly frame formats relies
793 : : // on anchoring at the start of the selection
794 : : // => selection backwards needs a correction.
795 [ # # ]: 0 : if( bBackSp )
796 [ # # ]: 0 : lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
797 : 0 : pTxtNd = aPos.nNode.GetNode().GetTxtNode();
798 : : }
799 [ # # ]: 0 : if( pTxtNd )
800 : : {
801 : : pTxtNd->InsertText( *pEndStr, aPos.nContent,
802 [ # # ]: 0 : IDocumentContentOperations::INS_NOHINTEXPAND );
803 : : // METADATA: restore
804 [ # # ]: 0 : pTxtNd->RestoreMetadata(m_pMetadataUndoEnd);
805 : : }
806 : : }
807 [ # # ][ # # ]: 0 : else if( pSttStr && bNodeMove )
808 : : {
809 : 0 : SwTxtNode * pNd = aPos.nNode.GetNode().GetTxtNode();
810 [ # # ]: 0 : if( pNd )
811 : : {
812 [ # # ]: 0 : if( nSttCntnt < pNd->GetTxt().Len() )
813 : : {
814 : 0 : sal_uLong nOldIdx = aPos.nNode.GetIndex();
815 [ # # ]: 0 : pDoc->SplitNode( aPos, false );
816 [ # # ]: 0 : if( bBackSp )
817 [ # # ]: 0 : lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
818 : : }
819 : : else
820 [ # # ]: 0 : aPos.nNode++;
821 : : }
822 : : }
823 : 0 : SwNode* pMovedNode = NULL;
824 [ # # ]: 0 : if( nSectDiff )
825 : : {
826 : 0 : sal_uLong nMoveIndex = aPos.nNode.GetIndex();
827 : 0 : int nDiff = 0;
828 [ # # ]: 0 : if( bJoinNext )
829 : : {
830 : 0 : nMoveIndex += nSectDiff + 1;
831 : 0 : pMovedNode = &aPos.nNode.GetNode();
832 : : }
833 : : else
834 : : {
835 : 0 : nMoveIndex -= nSectDiff + 1;
836 : 0 : ++nDiff;
837 : : }
838 [ # # ][ # # ]: 0 : SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
839 [ # # ]: 0 : SwNodeRange aRg( aPos.nNode, 0 - nDiff, aPos.nNode, 1 - nDiff );
840 [ # # ]: 0 : aPos.nNode--;
841 [ # # ]: 0 : if( !bJoinNext )
842 : 0 : pMovedNode = &aPos.nNode.GetNode();
843 [ # # ][ # # ]: 0 : pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
[ # # ]
844 [ # # ][ # # ]: 0 : aPos.nNode++;
[ # # ]
845 : : }
846 : :
847 [ # # ]: 0 : if( bNodeMove )
848 : : {
849 [ # # ]: 0 : SwNodeRange aRange( *pMvStt, 0, *pMvStt, nNode );
850 [ # # ]: 0 : SwNodeIndex aCopyIndex( aPos.nNode, -1 );
851 [ # # ][ # # ]: 0 : pDoc->GetUndoManager().GetUndoNodes()._Copy( aRange, aPos.nNode );
[ # # ]
852 : :
853 [ # # ]: 0 : if( nReplaceDummy )
854 : : {
855 : : sal_uLong nMoveIndex;
856 [ # # ]: 0 : if( bJoinNext )
857 : : {
858 : 0 : nMoveIndex = nEndNode - nNdDiff;
859 [ # # ]: 0 : aPos.nNode = nMoveIndex + nReplaceDummy;
860 : : }
861 : : else
862 : : {
863 [ # # ][ # # ]: 0 : aPos = SwPosition( aCopyIndex );
[ # # ]
864 : 0 : nMoveIndex = aPos.nNode.GetIndex() + nReplaceDummy + 1;
865 : : }
866 [ # # ][ # # ]: 0 : SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
867 [ # # ]: 0 : SwNodeRange aRg( aPos.nNode, 0, aPos.nNode, 1 );
868 : 0 : pMovedNode = &aPos.nNode.GetNode();
869 [ # # ][ # # ]: 0 : pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
[ # # ]
870 [ # # ][ # # ]: 0 : pDoc->GetNodes().Delete( aMvIdx, 1 );
[ # # ][ # # ]
871 [ # # ][ # # ]: 0 : }
872 : : }
873 : :
874 [ # # ]: 0 : if( pMovedNode )
875 [ # # ]: 0 : lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(), pMovedNode->GetIndex() );
876 : :
877 [ # # ]: 0 : if( pSttStr )
878 : : {
879 [ # # ][ # # ]: 0 : aPos.nNode = nSttNode - nNdDiff + ( bJoinNext ? 0 : nReplaceDummy );
880 : 0 : SwTxtNode * pTxtNd = aPos.nNode.GetNode().GetTxtNode();
881 : : // If more than a single Node got deleted, also all "Node"
882 : : // attributes were saved
883 [ # # ]: 0 : if (pTxtNd != NULL)
884 : : {
885 [ # # ][ # # ]: 0 : if( pTxtNd->HasSwAttrSet() && bNodeMove && !pEndStr )
[ # # ][ # # ]
[ # # ]
886 [ # # ]: 0 : pTxtNd->ResetAllAttr();
887 : :
888 [ # # ]: 0 : if( pTxtNd->GetpSwpHints() )
889 [ # # ]: 0 : pTxtNd->ClearSwpHintsArr( true );
890 : :
891 : : // SectionNode mode and selection from top to bottom:
892 : : // -> in StartNode is still the rest of the Join => delete
893 [ # # ][ # # ]: 0 : aPos.nContent.Assign( pTxtNd, nSttCntnt );
894 : : pTxtNd->InsertText( *pSttStr, aPos.nContent,
895 [ # # ]: 0 : IDocumentContentOperations::INS_NOHINTEXPAND );
896 : : // METADATA: restore
897 [ # # ]: 0 : pTxtNd->RestoreMetadata(m_pMetadataUndoStart);
898 : : }
899 : : }
900 : :
901 [ # # ]: 0 : if( pHistory )
902 : : {
903 [ # # ]: 0 : pHistory->TmpRollback( pDoc, nSetPos, false );
904 [ # # ]: 0 : if( nSetPos ) // there were Footnodes/FlyFrames
905 : : {
906 : : // are there others than these ones?
907 [ # # ]: 0 : if( nSetPos < pHistory->Count() )
908 : : {
909 : : // if so save the attributes of the others
910 [ # # ]: 0 : SwHistory aHstr;
911 [ # # ]: 0 : aHstr.Move( 0, pHistory, nSetPos );
912 [ # # ]: 0 : pHistory->Rollback( pDoc );
913 [ # # ][ # # ]: 0 : pHistory->Move( 0, &aHstr );
914 : : }
915 : : else
916 : : {
917 [ # # ]: 0 : pHistory->Rollback( pDoc );
918 [ # # ][ # # ]: 0 : DELETEZ( pHistory );
919 : : }
920 : : }
921 : : }
922 : :
923 [ # # ][ # # ]: 0 : if( bResetPgDesc || bResetPgBrk )
924 : : {
925 [ # # ]: 0 : sal_uInt16 nStt = static_cast<sal_uInt16>( bResetPgDesc ? RES_PAGEDESC : RES_BREAK );
926 [ # # ]: 0 : sal_uInt16 nEnd = static_cast<sal_uInt16>( bResetPgBrk ? RES_BREAK : RES_PAGEDESC );
927 : :
928 [ # # ][ # # ]: 0 : SwNode* pNode = pDoc->GetNodes()[ nEndNode + 1 ];
929 [ # # ]: 0 : if( pNode->IsCntntNode() )
930 [ # # ][ # # ]: 0 : ((SwCntntNode*)pNode)->ResetAttr( nStt, nEnd );
[ # # ][ # # ]
931 [ # # ]: 0 : else if( pNode->IsTableNode() )
932 [ # # ]: 0 : ((SwTableNode*)pNode)->GetTable().GetFrmFmt()->ResetFmtAttr( nStt, nEnd );
933 [ # # ]: 0 : }
934 : : }
935 : : // delete the temporarily added Node
936 [ # # ]: 0 : if( pInsNd )
937 [ # # ][ # # ]: 0 : pDoc->GetNodes().Delete( aIdx, 1 );
938 [ # # ]: 0 : if( pRedlSaveData )
939 [ # # ]: 0 : SetSaveData( *pDoc, *pRedlSaveData );
940 : :
941 [ # # ][ # # ]: 0 : AddUndoRedoPaM(rContext, true);
942 : 0 : }
943 : :
944 : 0 : void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
945 : : {
946 : 0 : SwPaM & rPam = AddUndoRedoPaM(rContext);
947 : 0 : SwDoc& rDoc = *rPam.GetDoc();
948 : :
949 [ # # ]: 0 : if( pRedlSaveData )
950 : : {
951 : 0 : bool bSuccess = FillSaveData(rPam, *pRedlSaveData, sal_True);
952 : : OSL_ENSURE(bSuccess,
953 : : "SwUndoDelete::Redo: used to have redline data, but now none?");
954 [ # # ]: 0 : if (!bSuccess)
955 : : {
956 [ # # ]: 0 : delete pRedlSaveData, pRedlSaveData = 0;
957 : : }
958 : : }
959 : :
960 [ # # ]: 0 : if( !bDelFullPara )
961 : : {
962 [ # # ]: 0 : SwUndRng aTmpRng( rPam );
963 [ # # ]: 0 : RemoveIdxFromRange( rPam, sal_False );
964 [ # # ]: 0 : aTmpRng.SetPaM( rPam );
965 : :
966 [ # # ]: 0 : if( !bJoinNext ) // then restore selection from bottom to top
967 : 0 : rPam.Exchange();
968 : : }
969 : :
970 [ # # ]: 0 : if( pHistory ) // are the attributes saved?
971 : : {
972 [ # # ]: 0 : pHistory->SetTmpEnd( pHistory->Count() );
973 [ # # ]: 0 : SwHistory aHstr;
974 [ # # ]: 0 : aHstr.Move( 0, pHistory );
975 : :
976 [ # # ]: 0 : if( bDelFullPara )
977 : : {
978 : : OSL_ENSURE( rPam.HasMark(), "PaM without Mark" );
979 : 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
980 [ # # ]: 0 : DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
981 : :
982 [ # # ]: 0 : _DelBookmarks(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
983 : : }
984 : : else
985 [ # # ]: 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
986 [ # # ]: 0 : nSetPos = pHistory ? pHistory->Count() : 0;
987 : :
988 [ # # ][ # # ]: 0 : pHistory->Move( nSetPos, &aHstr );
989 : : }
990 : : else
991 : : {
992 [ # # ]: 0 : if( bDelFullPara )
993 : : {
994 : : OSL_ENSURE( rPam.HasMark(), "PaM without Mark" );
995 : 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
996 : 0 : DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
997 : :
998 : 0 : _DelBookmarks( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
999 : : }
1000 : : else
1001 : 0 : DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
1002 [ # # ]: 0 : nSetPos = pHistory ? pHistory->Count() : 0;
1003 : : }
1004 : :
1005 [ # # ][ # # ]: 0 : if( !pSttStr && !pEndStr )
1006 : : {
1007 : : SwNodeIndex aSttIdx = ( bDelFullPara || bJoinNext )
1008 : 0 : ? rPam.GetMark()->nNode
1009 [ # # ][ # # ]: 0 : : rPam.GetPoint()->nNode;
[ # # ]
1010 : 0 : SwTableNode* pTblNd = aSttIdx.GetNode().GetTableNode();
1011 [ # # ]: 0 : if( pTblNd )
1012 : : {
1013 [ # # ]: 0 : if( bTblDelLastNd )
1014 : : {
1015 : : // than add again a Node at the end
1016 [ # # ]: 0 : const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
1017 [ # # ]: 0 : rDoc.GetNodes().MakeTxtNode( aTmpIdx,
1018 [ # # ][ # # ]: 0 : rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
[ # # ]
1019 : : }
1020 : :
1021 [ # # ]: 0 : SwCntntNode* pNextNd = rDoc.GetNodes()[
1022 [ # # ]: 0 : pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
1023 [ # # ]: 0 : if( pNextNd )
1024 : : {
1025 : 0 : SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
1026 : :
1027 : : const SfxPoolItem *pItem;
1028 [ # # ]: 0 : if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
1029 [ # # ]: 0 : sal_False, &pItem ) )
1030 [ # # ]: 0 : pNextNd->SetAttr( *pItem );
1031 : :
1032 [ # # ]: 0 : if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
1033 [ # # ]: 0 : sal_False, &pItem ) )
1034 [ # # ]: 0 : pNextNd->SetAttr( *pItem );
1035 : : }
1036 [ # # ]: 0 : pTblNd->DelFrms();
1037 : : }
1038 : :
1039 [ # # ]: 0 : rPam.SetMark();
1040 [ # # ]: 0 : rPam.DeleteMark();
1041 : :
1042 [ # # ][ # # ]: 0 : rDoc.GetNodes().Delete( aSttIdx, nEndNode - nSttNode );
1043 : :
1044 : : // always set the cursor into a ContentNode!
1045 [ # # ][ # # ]: 0 : if( !rPam.Move( fnMoveBackward, fnGoCntnt ) &&
[ # # ][ # # ]
1046 [ # # ]: 0 : !rPam.Move( fnMoveForward, fnGoCntnt ) )
1047 [ # # ][ # # ]: 0 : rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
[ # # ]
1048 : : }
1049 [ # # ]: 0 : else if( bDelFullPara )
1050 : : {
1051 : : // The Pam was incremented by one at Point (== end) to provide space
1052 : : // for UNDO. This now needs to be reverted!
1053 : 0 : rPam.End()->nNode--;
1054 [ # # ]: 0 : if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
1055 : 0 : *rPam.GetMark() = *rPam.GetPoint();
1056 : 0 : rDoc.DelFullPara( rPam );
1057 : : }
1058 : : else
1059 : 0 : rDoc.DeleteAndJoin( rPam );
1060 : 0 : }
1061 : :
1062 : 0 : void SwUndoDelete::RepeatImpl(::sw::RepeatContext & rContext)
1063 : : {
1064 : : // this action does not seem idempotent,
1065 : : // so make sure it is only executed once on repeat
1066 [ # # ]: 0 : if (rContext.m_bDeleteRepeated)
1067 : 0 : return;
1068 : :
1069 : 0 : SwPaM & rPam = rContext.GetRepeatPaM();
1070 : 0 : SwDoc& rDoc = *rPam.GetDoc();
1071 [ # # ][ # # ]: 0 : ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1072 [ # # ]: 0 : if( !rPam.HasMark() )
1073 : : {
1074 [ # # ]: 0 : rPam.SetMark();
1075 [ # # ]: 0 : rPam.Move( fnMoveForward, fnGoCntnt );
1076 : : }
1077 [ # # ]: 0 : if( bDelFullPara )
1078 [ # # ]: 0 : rDoc.DelFullPara( rPam );
1079 : : else
1080 [ # # ]: 0 : rDoc.DeleteAndJoin( rPam );
1081 [ # # ]: 0 : rContext.m_bDeleteRepeated = true;
1082 : : }
1083 : :
1084 : :
1085 : 8 : void SwUndoDelete::SetTableName(const String & rName)
1086 : : {
1087 : 8 : sTableName = rName;
1088 : 8 : }
1089 : :
1090 : 17479 : String SwRewriter::Apply(const String & rStr) const
1091 : : {
1092 [ + - ]: 17479 : rtl::OUString aResult = rStr;
1093 : 17479 : std::vector<SwRewriteRule>::const_iterator aIt;
1094 : :
1095 [ + - ][ + - ]: 30832 : for (aIt = mRules.begin(); aIt != mRules.end(); ++aIt)
[ + + ]
1096 : : {
1097 [ + - ]: 13353 : switch (aIt->first)
[ + + + ]
1098 : : {
1099 : : case UndoArg1:
1100 : : default:
1101 [ + - ][ + - ]: 12639 : aResult = aResult.replaceAll(UNDO_ARG1, aIt->second);
1102 : 12639 : break;
1103 : : case UndoArg2:
1104 [ + - ][ + - ]: 530 : aResult = aResult.replaceAll(UNDO_ARG2, aIt->second);
1105 : 530 : break;
1106 : : case UndoArg3:
1107 [ + - ][ + - ]: 184 : aResult = aResult.replaceAll(UNDO_ARG3, aIt->second);
1108 : 184 : break;
1109 : : }
1110 : : }
1111 : :
1112 [ + - ]: 17479 : return aResult;
1113 : : }
1114 : :
1115 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|