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

Generated by: LCOV version 1.11