LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/undo - undel.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 231 542 42.6 %
Date: 2013-07-09 Functions: 13 19 68.4 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10