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

Generated by: LCOV version 1.10