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

Generated by: LCOV version 1.10