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