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

Generated by: LCOV version 1.10