LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/doc - docedt.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 320 1402 22.8 %
Date: 2012-12-27 Functions: 20 57 35.1 %
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             : 
      21             : #include <string.h>         // for strchr()
      22             : #include <hintids.hxx>
      23             : 
      24             : #include <editeng/cscoitem.hxx>
      25             : #include <editeng/brkitem.hxx>
      26             : #include <linguistic/lngprops.hxx>
      27             : #include <com/sun/star/beans/XPropertySet.hpp>
      28             : #include <com/sun/star/i18n/WordType.hpp>
      29             : #include <unotools/charclass.hxx>
      30             : #include <unotools/transliterationwrapper.hxx>
      31             : #include <fmtanchr.hxx>
      32             : #include <fmtcntnt.hxx>
      33             : #include <fmtpdsc.hxx>
      34             : #include <txtftn.hxx>
      35             : #include <acorrect.hxx>     // AutoCorrect
      36             : #include <IMark.hxx>        // for SwBookmark
      37             : #include <cntfrm.hxx>       // for Spell
      38             : #include <crsrsh.hxx>
      39             : #include <doc.hxx>
      40             : #include <UndoManager.hxx>
      41             : #include <docsh.hxx>
      42             : #include <docary.hxx>
      43             : #include <doctxm.hxx>       // when moving: correct indexes
      44             : #include <ftnidx.hxx>
      45             : #include <ftninfo.hxx>
      46             : #include <mdiexp.hxx>       // status bar
      47             : #include <mvsave.hxx>       // structures to save when moving/deleting
      48             : #include <ndtxt.hxx>
      49             : #include <pam.hxx>
      50             : #include <redline.hxx>
      51             : #include <rootfrm.hxx>      // for UpdateFtn
      52             : #include <splargs.hxx>      // for Spell
      53             : #include <swtable.hxx>
      54             : #include <swundo.hxx>       // for the UndoIds
      55             : #include <txtfrm.hxx>
      56             : #include <hints.hxx>
      57             : #include <UndoSplitMove.hxx>
      58             : #include <UndoRedline.hxx>
      59             : #include <UndoOverwrite.hxx>
      60             : #include <UndoInsert.hxx>
      61             : #include <UndoDelete.hxx>
      62             : #include <breakit.hxx>
      63             : #include <hhcwrp.hxx>
      64             : #include <vcl/msgbox.hxx>
      65             : #include "comcore.hrc"
      66             : #include "editsh.hxx"
      67             : #include <fldbas.hxx>
      68             : #include <fmtfld.hxx>
      69             : #include <docufld.hxx>
      70             : #include <unoflatpara.hxx>
      71             : #include <SwGrammarMarkUp.hxx>
      72             : 
      73             : #include <vector>
      74             : 
      75             : using ::rtl::OUString;
      76             : using namespace ::com::sun::star;
      77             : using namespace ::com::sun::star::linguistic2;
      78             : using namespace ::com::sun::star::i18n;
      79             : 
      80             : #ifndef S2U
      81             : #define S2U(rString) OUString::createFromAscii(rString)
      82             : #endif
      83             : 
      84             : struct _SaveRedline
      85             : {
      86             :     SwRedline* pRedl;
      87             :     sal_uInt32 nStt, nEnd;
      88             :     xub_StrLen nSttCnt, nEndCnt;
      89             : 
      90           0 :     _SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
      91           0 :         : pRedl( pR )
      92             :     {
      93           0 :         const SwPosition* pStt = pR->Start(),
      94           0 :             * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
      95           0 :         sal_uInt32 nSttIdx = rSttIdx.GetIndex();
      96           0 :         nStt = pStt->nNode.GetIndex() - nSttIdx;
      97           0 :         nSttCnt = pStt->nContent.GetIndex();
      98           0 :         if( pR->HasMark() )
      99             :         {
     100           0 :             nEnd = pEnd->nNode.GetIndex() - nSttIdx;
     101           0 :             nEndCnt = pEnd->nContent.GetIndex();
     102             :         }
     103             : 
     104           0 :         pRedl->GetPoint()->nNode = 0;
     105           0 :         pRedl->GetPoint()->nContent.Assign( 0, 0 );
     106           0 :         pRedl->GetMark()->nNode = 0;
     107           0 :         pRedl->GetMark()->nContent.Assign( 0, 0 );
     108           0 :     }
     109             : 
     110           0 :     _SaveRedline( SwRedline* pR, const SwPosition& rPos )
     111           0 :         : pRedl( pR )
     112             :     {
     113           0 :         const SwPosition* pStt = pR->Start(),
     114           0 :             * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
     115           0 :         sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
     116           0 :         nStt = pStt->nNode.GetIndex() - nSttIdx;
     117           0 :         nSttCnt = pStt->nContent.GetIndex();
     118           0 :         if( nStt == 0 )
     119           0 :             nSttCnt = nSttCnt - rPos.nContent.GetIndex();
     120           0 :         if( pR->HasMark() )
     121             :         {
     122           0 :             nEnd = pEnd->nNode.GetIndex() - nSttIdx;
     123           0 :             nEndCnt = pEnd->nContent.GetIndex();
     124           0 :             if( nEnd == 0 )
     125           0 :                 nEndCnt = nEndCnt - rPos.nContent.GetIndex();
     126             :         }
     127             : 
     128           0 :         pRedl->GetPoint()->nNode = 0;
     129           0 :         pRedl->GetPoint()->nContent.Assign( 0, 0 );
     130           0 :         pRedl->GetMark()->nNode = 0;
     131           0 :         pRedl->GetMark()->nContent.Assign( 0, 0 );
     132           0 :     }
     133             : 
     134           0 :     void SetPos( sal_uInt32 nInsPos )
     135             :     {
     136           0 :         pRedl->GetPoint()->nNode = nInsPos + nStt;
     137           0 :         pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
     138           0 :         if( pRedl->HasMark() )
     139             :         {
     140           0 :             pRedl->GetMark()->nNode = nInsPos + nEnd;
     141           0 :             pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
     142             :         }
     143           0 :     }
     144             : 
     145           0 :     void SetPos( const SwPosition& aPos )
     146             :     {
     147           0 :         pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
     148           0 :         pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
     149           0 :         if( pRedl->HasMark() )
     150             :         {
     151           0 :             pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
     152           0 :             pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt  + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
     153             :         }
     154           0 :     }
     155             : };
     156             : 
     157             : typedef boost::ptr_vector< _SaveRedline > _SaveRedlines;
     158             : 
     159           0 : static bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
     160             : {
     161           0 :     sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
     162             :     return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
     163           0 :               (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
     164             : }
     165             : 
     166           0 : static void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
     167             : {
     168           0 :     if( !lcl_MayOverwrite( pNode, rStart ) )
     169             :     {
     170             :         // skip all special attributes
     171           0 :         do {
     172           0 :             ++rIdx;
     173           0 :         } while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
     174           0 :                && !lcl_MayOverwrite(pNode, rStart) );
     175             :     }
     176           0 : }
     177             : 
     178           0 : void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
     179             :                       const SwNodeIndex* pInsertPos )
     180             : {
     181           0 :     SwPosition aPos( rSttIdx );
     182           0 :     for( size_t n = 0; n < rArr.size(); ++n )
     183             :     {
     184             :         // create new anchor
     185           0 :         _SaveFly& rSave = rArr[n];
     186           0 :         SwFrmFmt* pFmt = rSave.pFrmFmt;
     187             : 
     188           0 :         if( rSave.bInsertPosition )
     189             :         {
     190           0 :             if( pInsertPos != NULL )
     191           0 :                 aPos.nNode = *pInsertPos;
     192             :             else
     193           0 :                 aPos.nNode = rSttIdx.GetIndex();
     194             :         }
     195             :         else
     196           0 :             aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
     197             : 
     198           0 :         aPos.nContent.Assign( 0, 0 );
     199           0 :         SwFmtAnchor aAnchor( pFmt->GetAnchor() );
     200           0 :         aAnchor.SetAnchor( &aPos );
     201           0 :         pFmt->GetDoc()->GetSpzFrmFmts()->push_back( pFmt );
     202           0 :         pFmt->SetFmtAttr( aAnchor );
     203           0 :         SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
     204           0 :         if( pCNd && pCNd->getLayoutFrm( pFmt->GetDoc()->GetCurrentLayout(), 0, 0, sal_False ) )
     205           0 :             pFmt->MakeFrms();
     206           0 :     }
     207           0 : }
     208             : 
     209           0 : void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
     210             : {
     211           0 :     SwFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
     212           0 :     for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
     213             :     {
     214           0 :         SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
     215           0 :         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
     216           0 :         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
     217           0 :         if (pAPos &&
     218           0 :             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
     219           0 :              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
     220           0 :             rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
     221             :         {
     222           0 :             _SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
     223           0 :                             pFmt, false );
     224           0 :             rArr.push_back( aSave );
     225           0 :             pFmt->DelFrms();
     226           0 :             rFmts.erase( rFmts.begin() + n-- );
     227             :         }
     228             :     }
     229           0 : }
     230             : 
     231           0 : void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
     232             :                        _SaveFlyArr& rArr, bool bMoveAllFlys )
     233             : {
     234           0 :     SwFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
     235             :     SwFrmFmt* pFmt;
     236             :     const SwFmtAnchor* pAnchor;
     237             : 
     238           0 :     const SwPosition* pPos = rPam.Start();
     239           0 :     const SwNodeIndex& rSttNdIdx = pPos->nNode;
     240           0 :     short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
     241           0 :                     pPos->nContent.GetIndex()) ? 1 : 0;
     242             : 
     243           0 :     pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
     244           0 :     const SwNodeIndex& rEndNdIdx = pPos->nNode;
     245           0 :     short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
     246           0 :                 pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
     247           0 :                     ? 0 : 1;
     248             : 
     249             :     const SwNodeIndex* pCntntIdx;
     250             : 
     251           0 :     for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
     252             :     {
     253           0 :         bool bInsPos = false;
     254           0 :         pFmt = (SwFrmFmt*)rFmts[n];
     255           0 :         pAnchor = &pFmt->GetAnchor();
     256           0 :         const SwPosition* pAPos = pAnchor->GetCntntAnchor();
     257           0 :         if (pAPos &&
     258           0 :             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
     259           0 :              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
     260             :             // do not move if the InsPos is in the CntntArea of the Fly
     261           0 :             ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
     262           0 :               !( *pCntntIdx < rInsPos &&
     263           0 :                 rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
     264             :         {
     265           0 :             if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
     266             :             {
     267             :                 // Do not touch Anchor, if only a part of the EndNode
     268             :                 // or the whole EndNode is identical with the SttNode
     269           0 :                 if( rSttNdIdx != pAPos->nNode )
     270             :                 {
     271             :                     // Only attach an anchor to the beginning or end
     272           0 :                     SwPosition aPos( rSttNdIdx );
     273           0 :                     SwFmtAnchor aAnchor( *pAnchor );
     274           0 :                     aAnchor.SetAnchor( &aPos );
     275           0 :                     pFmt->SetFmtAttr( aAnchor );
     276             :                 }
     277             :             }
     278           0 :             else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
     279           0 :                     && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
     280           0 :                         0 != ( bInsPos = rInsPos == pAPos->nNode ))
     281             : 
     282             :             {
     283           0 :                 _SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
     284           0 :                                 pFmt, bInsPos );
     285           0 :                 rArr.push_back( aSave );
     286           0 :                 pFmt->DelFrms();
     287           0 :                 rFmts.erase( rFmts.begin() + n-- );
     288             :             }
     289             :         }
     290             :     }
     291           0 : }
     292             : 
     293             : // Delete and move all Flys at the paragraph, that are within the selection.
     294             : // If there is a Fly at the SPoint, it is moved onto the Mark.
     295         488 : void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
     296             :                     const SwNodeIndex& rPtNdIdx )
     297             : {
     298         488 :     const bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
     299             : 
     300         488 :     SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
     301         488 :     SwFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
     302        1310 :     for ( sal_uInt16 i = rTbl.size(); i; )
     303             :     {
     304         334 :         SwFrmFmt *pFmt = rTbl[--i];
     305         334 :         const SwFmtAnchor &rAnch = pFmt->GetAnchor();
     306         334 :         SwPosition const*const pAPos = rAnch.GetCntntAnchor();
     307        1055 :         if (pAPos &&
     308         320 :             ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
     309         254 :              (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
     310             :             ( bDelFwrd
     311         147 :                 ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
     312           0 :                 : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
     313             :         {
     314             :             // Only move the Anchor??
     315           9 :             if( rPtNdIdx == pAPos->nNode )
     316             :             {
     317           3 :                 SwFmtAnchor aAnch( pFmt->GetAnchor() );
     318           3 :                 SwPosition aPos( rMkNdIdx );
     319           3 :                 aAnch.SetAnchor( &aPos );
     320           3 :                 pFmt->SetFmtAttr( aAnch );
     321             :             }
     322             :             else
     323             :             {
     324             :                 // If the Fly is deleted, all Flys in it's content have to be deleted too.
     325           6 :                 const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
     326           6 :                 if( rCntnt.GetCntntIdx() )
     327             :                 {
     328           3 :                     DelFlyInRange( *rCntnt.GetCntntIdx(),
     329             :                                     SwNodeIndex( *rCntnt.GetCntntIdx()->
     330           6 :                                             GetNode().EndOfSectionNode() ));
     331             :                     // Position could have been moved!
     332           3 :                     if( i > rTbl.size() )
     333           0 :                         i = rTbl.size();
     334           3 :                     else if( pFmt != rTbl[i] )
     335           0 :                         i = rTbl.GetPos( pFmt );
     336             :                 }
     337             : 
     338           6 :                 pDoc->DelLayoutFmt( pFmt );
     339             : 
     340             :                 // DelLayoutFmt can also trigger the deletion of objects.
     341           6 :                 if( i > rTbl.size() )
     342           0 :                     i = rTbl.size();
     343             :             }
     344             :         }
     345             :     }
     346         488 : }
     347             : 
     348           0 : static bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
     349             :                  const SwNodeIndex& rInsPos,
     350             :                  SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
     351             :                  const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
     352             : {
     353           0 :     bool bUpdateFtn = sal_False;
     354           0 :     const SwNodes& rNds = rInsPos.GetNodes();
     355           0 :     const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
     356           0 :                 rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
     357           0 :     const bool bSaveFtn = !bDelFtn &&
     358           0 :                     rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
     359           0 :     if( !rFtnArr.empty() )
     360             :     {
     361             : 
     362             :         sal_uInt16 nPos;
     363           0 :         rFtnArr.SeekEntry( rSttNd, &nPos );
     364             :         SwTxtFtn* pSrch;
     365             :         const SwNode* pFtnNd;
     366             : 
     367             :         // Delete/save all that come after it
     368           0 :         while( nPos < rFtnArr.size() && ( pFtnNd =
     369           0 :             &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
     370           0 :                     <= rEndNd.GetIndex() )
     371             :         {
     372           0 :             xub_StrLen nFtnSttIdx = *pSrch->GetStart();
     373           0 :             if( ( pEndCnt && pSttCnt )
     374           0 :                 ? (( &rSttNd.GetNode() == pFtnNd &&
     375           0 :                      pSttCnt->GetIndex() > nFtnSttIdx) ||
     376           0 :                    ( &rEndNd.GetNode() == pFtnNd &&
     377           0 :                     nFtnSttIdx >= pEndCnt->GetIndex() ))
     378           0 :                 : ( &rEndNd.GetNode() == pFtnNd ))
     379             :             {
     380           0 :                 ++nPos;     // continue searching
     381             :             }
     382             :             else
     383             :             {
     384             :                 // delete it
     385           0 :                 if( bDelFtn )
     386             :                 {
     387           0 :                     SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
     388           0 :                     SwIndex aIdx( &rTxtNd, nFtnSttIdx );
     389           0 :                     rTxtNd.EraseText( aIdx, 1 );
     390             :                 }
     391             :                 else
     392             :                 {
     393           0 :                     pSrch->DelFrms(0);
     394           0 :                     rFtnArr.erase( rFtnArr.begin() + nPos );
     395           0 :                     if( bSaveFtn )
     396           0 :                         rSaveArr.insert( pSrch );
     397             :                 }
     398           0 :                 bUpdateFtn = sal_True;
     399             :             }
     400             :         }
     401             : 
     402           0 :         while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
     403           0 :                 GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
     404             :         {
     405           0 :             xub_StrLen nFtnSttIdx = *pSrch->GetStart();
     406           0 :             if( !pEndCnt || !pSttCnt ||
     407           0 :                 !( (( &rSttNd.GetNode() == pFtnNd &&
     408           0 :                     pSttCnt->GetIndex() > nFtnSttIdx ) ||
     409           0 :                    ( &rEndNd.GetNode() == pFtnNd &&
     410           0 :                     nFtnSttIdx >= pEndCnt->GetIndex() )) ))
     411             :             {
     412           0 :                 if( bDelFtn )
     413             :                 {
     414             :                     // delete it
     415           0 :                     SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
     416           0 :                     SwIndex aIdx( &rTxtNd, nFtnSttIdx );
     417           0 :                     rTxtNd.EraseText( aIdx, 1 );
     418             :                 }
     419             :                 else
     420             :                 {
     421           0 :                     pSrch->DelFrms(0);
     422           0 :                     rFtnArr.erase( rFtnArr.begin() + nPos );
     423           0 :                     if( bSaveFtn )
     424           0 :                         rSaveArr.insert( pSrch );
     425             :                 }
     426           0 :                 bUpdateFtn = sal_True;
     427             :             }
     428             :         }
     429             :     }
     430             :     // When moving from redline section into document content section, e.g.
     431             :     // after loading a document with (delete-)redlines, the footnote array
     432             :     // has to be adjusted... (#i70572)
     433           0 :     if( bSaveFtn )
     434             :     {
     435           0 :         SwNodeIndex aIdx( rSttNd );
     436           0 :         while( aIdx < rEndNd ) // Check the moved section
     437             :         {
     438           0 :             SwNode* pNode = &aIdx.GetNode();
     439           0 :             if( pNode->IsTxtNode() ) // Looking for text nodes...
     440             :             {
     441             :                 SwpHints *pHints =
     442           0 :                     static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
     443           0 :                 if( pHints && pHints->HasFtn() ) //...with footnotes
     444             :                 {
     445           0 :                     bUpdateFtn = sal_True; // Heureka
     446           0 :                     sal_uInt16 nCount = pHints->Count();
     447           0 :                     for( sal_uInt16 i = 0; i < nCount; ++i )
     448             :                     {
     449           0 :                         SwTxtAttr *pAttr = pHints->GetTextHint( i );
     450           0 :                         if ( pAttr->Which() == RES_TXTATR_FTN )
     451             :                         {
     452           0 :                             rSaveArr.insert( static_cast<SwTxtFtn*>(pAttr) );
     453             :                         }
     454             :                     }
     455             :                 }
     456             :             }
     457           0 :             ++aIdx;
     458           0 :         }
     459             :     }
     460           0 :     return bUpdateFtn;
     461             : }
     462             : 
     463           0 : static void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
     464             : {
     465           0 :     SwDoc* pDoc = aPam.GetNode()->GetDoc();
     466             : 
     467           0 :     const SwPosition* pStart = aPam.Start();
     468           0 :     const SwPosition* pEnd = aPam.End();
     469             : 
     470             :     // get first relevant redline
     471             :     sal_uInt16 nCurrentRedline;
     472           0 :     pDoc->GetRedline( *pStart, &nCurrentRedline );
     473           0 :     if( nCurrentRedline > 0)
     474           0 :         nCurrentRedline--;
     475             : 
     476             :     // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
     477           0 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     478           0 :     pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
     479             : 
     480             :     // iterate over relevant redlines and decide for each whether it should
     481             :     // be saved, or split + saved
     482           0 :     SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->GetRedlineTbl() );
     483           0 :     for( ; nCurrentRedline < rRedlineTable.size(); nCurrentRedline++ )
     484             :     {
     485           0 :         SwRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
     486             :         SwComparePosition eCompare =
     487           0 :             ComparePosition( *pCurrent->Start(), *pCurrent->End(),
     488           0 :                              *pStart, *pEnd);
     489             : 
     490             :         // we must save this redline if it overlaps aPam
     491             :         // (we may have to split it, too)
     492           0 :         if( eCompare == POS_OVERLAP_BEHIND  ||
     493             :             eCompare == POS_OVERLAP_BEFORE  ||
     494             :             eCompare == POS_OUTSIDE ||
     495             :             eCompare == POS_INSIDE ||
     496             :             eCompare == POS_EQUAL )
     497             :         {
     498           0 :             rRedlineTable.Remove( nCurrentRedline-- );
     499             : 
     500             :             // split beginning, if necessary
     501           0 :             if( eCompare == POS_OVERLAP_BEFORE  ||
     502             :                 eCompare == POS_OUTSIDE )
     503             :             {
     504             : 
     505           0 :                 SwRedline* pNewRedline = new SwRedline( *pCurrent );
     506           0 :                 *pNewRedline->End() = *pStart;
     507           0 :                 *pCurrent->Start() = *pStart;
     508           0 :                 pDoc->AppendRedline( pNewRedline, true );
     509             :             }
     510             : 
     511             :             // split end, if necessary
     512           0 :             if( eCompare == POS_OVERLAP_BEHIND  ||
     513             :                 eCompare == POS_OUTSIDE )
     514             :             {
     515           0 :                 SwRedline* pNewRedline = new SwRedline( *pCurrent );
     516           0 :                 *pNewRedline->Start() = *pEnd;
     517           0 :                 *pCurrent->End() = *pEnd;
     518           0 :                 pDoc->AppendRedline( pNewRedline, true );
     519             :             }
     520             : 
     521             :             // save the current redline
     522           0 :             _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
     523           0 :             rArr.push_back( pSave );
     524             :         }
     525             :     }
     526             : 
     527             :     // restore old redline mode
     528           0 :     pDoc->SetRedlineMode_intern( eOld );
     529           0 : }
     530             : 
     531           0 : static void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
     532             : {
     533           0 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     534           0 :     pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
     535             : 
     536           0 :     for( size_t n = 0; n < rArr.size(); ++n )
     537             :     {
     538           0 :         rArr[ n ].SetPos( rPos );
     539           0 :         pDoc->AppendRedline( rArr[ n ].pRedl, true );
     540             :     }
     541             : 
     542           0 :     pDoc->SetRedlineMode_intern( eOld );
     543           0 : }
     544             : 
     545           0 : static void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
     546             : {
     547           0 :     SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
     548             :     sal_uInt16 nRedlPos;
     549           0 :     SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
     550           0 :     aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
     551           0 :     if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
     552           0 :         --nRedlPos;
     553           0 :     else if( nRedlPos >= pDoc->GetRedlineTbl().size() )
     554           0 :         return ;
     555             : 
     556           0 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     557           0 :     pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
     558           0 :     SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
     559             : 
     560           0 :     do {
     561           0 :         SwRedline* pTmp = rRedlTbl[ nRedlPos ];
     562             : 
     563           0 :         const SwPosition* pRStt = pTmp->Start(),
     564           0 :                         * pREnd = pTmp->GetMark() == pRStt
     565           0 :                             ? pTmp->GetPoint() : pTmp->GetMark();
     566             : 
     567           0 :         if( pRStt->nNode < rRg.aStart )
     568             :         {
     569           0 :             if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
     570             :             {
     571             :                 // Create a copy and set the end of the original to the end of the MoveArea.
     572             :                 // The copy is moved too.
     573           0 :                 SwRedline* pNewRedl = new SwRedline( *pTmp );
     574           0 :                 SwPosition* pTmpPos = pNewRedl->Start();
     575           0 :                 pTmpPos->nNode = rRg.aStart;
     576             :                 pTmpPos->nContent.Assign(
     577           0 :                             pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
     578             : 
     579           0 :                 _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
     580           0 :                 rArr.push_back( pSave );
     581             : 
     582           0 :                 pTmpPos = pTmp->End();
     583           0 :                 pTmpPos->nNode = rRg.aEnd;
     584             :                 pTmpPos->nContent.Assign(
     585           0 :                             pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
     586             :             }
     587           0 :             else if( pREnd->nNode == rRg.aStart )
     588             :             {
     589           0 :                 SwPosition* pTmpPos = pTmp->End();
     590           0 :                 pTmpPos->nNode = rRg.aEnd;
     591             :                 pTmpPos->nContent.Assign(
     592           0 :                             pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
     593             :             }
     594             :         }
     595           0 :         else if( pRStt->nNode < rRg.aEnd )
     596             :         {
     597           0 :             rRedlTbl.Remove( nRedlPos-- );
     598           0 :             if( pREnd->nNode < rRg.aEnd ||
     599           0 :                 ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
     600             :             {
     601             :                 // move everything
     602           0 :                 _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
     603           0 :                 rArr.push_back( pSave );
     604             :             }
     605             :             else
     606             :             {
     607             :                 // split
     608           0 :                 SwRedline* pNewRedl = new SwRedline( *pTmp );
     609           0 :                 SwPosition* pTmpPos = pNewRedl->End();
     610           0 :                 pTmpPos->nNode = rRg.aEnd;
     611             :                 pTmpPos->nContent.Assign(
     612           0 :                             pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
     613             : 
     614           0 :                 _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
     615           0 :                 rArr.push_back( pSave );
     616             : 
     617           0 :                 pTmpPos = pTmp->Start();
     618           0 :                 pTmpPos->nNode = rRg.aEnd;
     619             :                 pTmpPos->nContent.Assign(
     620           0 :                             pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
     621           0 :                 pDoc->AppendRedline( pTmp, true );
     622             :             }
     623             :         }
     624             :         else
     625           0 :             break;
     626             : 
     627           0 :     } while( ++nRedlPos < pDoc->GetRedlineTbl().size() );
     628           0 :     pDoc->SetRedlineMode_intern( eOld );
     629             : }
     630             : 
     631           0 : static void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
     632             : {
     633           0 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     634           0 :     pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
     635             : 
     636           0 :     for( size_t n = 0; n < rArr.size(); ++n )
     637             :     {
     638           0 :         rArr[ n ].SetPos( nInsPos );
     639           0 :         pDoc->AppendRedline( rArr[ n ].pRedl, true );
     640             :     }
     641             : 
     642           0 :     pDoc->SetRedlineMode_intern( eOld );
     643           0 : }
     644             : 
     645             : // #i59534: Redo of insertion of multiple text nodes runs into trouble
     646             : // because of unnecessary expanded redlines
     647             : // From now on this class saves the redline positions of all redlines which ends exact at the
     648             : // insert position (node _and_ content index)
     649          18 : _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCnt )
     650          18 :     : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
     651             : {
     652          18 :     SwNode& rNd = rInsIdx.GetNode();
     653          18 :     SwDoc* pDest = rNd.GetDoc();
     654          18 :     if( !pDest->GetRedlineTbl().empty() )
     655             :     {
     656             :         sal_uInt16 nFndPos;
     657             :         const SwPosition* pEnd;
     658           0 :         SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
     659           0 :         const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
     660           0 :         while( nFndPos--
     661           0 :               && *( pEnd = ( pRedl = pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos
     662           0 :               && *pRedl->Start() < aSrcPos )
     663             :         {
     664           0 :             if( !pSavArr )
     665             :             {
     666           0 :                 pSavArr = new std::vector<SwPosition*>;
     667           0 :                 pSavIdx = new SwNodeIndex( rInsIdx, -1 );
     668             :             }
     669           0 :             pSavArr->push_back( (SwPosition*)pEnd );
     670           0 :         }
     671             :     }
     672          18 : }
     673             : 
     674          18 : _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
     675             : {
     676          18 :     delete pSavArr;
     677          18 :     delete pSavIdx;
     678          18 : }
     679             : 
     680           0 : void _SaveRedlEndPosForRestore::_Restore()
     681             : {
     682           0 :     ++(*pSavIdx);
     683           0 :     SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
     684             :     // If there's no content node at the remembered position, we will not restore the old position
     685             :     // This may happen if a table (or section?) will be inserted.
     686           0 :     if( pNode )
     687             :     {
     688           0 :         SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
     689           0 :         for( sal_uInt16 n = pSavArr->size(); n; )
     690           0 :             *(*pSavArr)[ --n ] = aPos;
     691             :     }
     692           0 : }
     693             : 
     694             : // Delete a full Section of the NodeArray.
     695             : // The passed Node is located somewhere in the designated Section.
     696         181 : void SwDoc::DeleteSection( SwNode *pNode )
     697             : {
     698             :     OSL_ENSURE( pNode, "Didn't pass a Node." );
     699         181 :     SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
     700         181 :                                                : pNode->StartOfSectionNode();
     701         181 :     SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
     702             : 
     703             :     // delete all Flys, Bookmarks, ...
     704         181 :     DelFlyInRange( aSttIdx, aEndIdx );
     705         181 :     DeleteRedline( *pSttNd, true, USHRT_MAX );
     706         181 :     _DelBookmarks(aSttIdx, aEndIdx);
     707             : 
     708             :     {
     709             :         // move all Crsr/StkCrsr/UnoCrsr out of the to-be-deleted area
     710         181 :         SwNodeIndex aMvStt( aSttIdx, 1 );
     711         181 :         CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
     712             :     }
     713             : 
     714         181 :     GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
     715         181 : }
     716             : 
     717           0 : void SwDoc::SetModified(SwPaM &rPaM)
     718             : {
     719           0 :     SwDataChanged aTmp( rPaM );
     720           0 :     SetModified();
     721           0 : }
     722             : 
     723             : /*************************************************************************
     724             :  * SwDoc::Overwrite()
     725             :  ************************************************************************/
     726        1290 : bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
     727             : {
     728        1290 :     SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
     729        1290 :     if( pACEWord )                  // Add to AutoCorrect
     730             :     {
     731           0 :         if( 1 == rStr.Len() )
     732           0 :             pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
     733           0 :         delete pACEWord, pACEWord = 0;
     734             :     }
     735             : 
     736        1290 :     SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
     737        1290 :     if(!pNode)
     738         644 :         return sal_False;
     739             : 
     740         646 :     if (GetIDocumentUndoRedo().DoesUndo())
     741             :     {
     742           0 :         GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
     743             :     }
     744             : 
     745         646 :     sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
     746         646 :                                 ? pNode->GetpSwpHints()->Count() : 0;
     747         646 :     SwDataChanged aTmp( rRg );
     748         646 :     SwIndex& rIdx = rPt.nContent;
     749         646 :     xub_StrLen nStart = 0;
     750             : 
     751         646 :     bool bOldExpFlg = pNode->IsIgnoreDontExpand();
     752         646 :     pNode->SetIgnoreDontExpand( true );
     753             : 
     754        4103 :     for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
     755             :     {
     756             :         // start behind the characters (to fix the attributes!)
     757        3457 :         nStart = rIdx.GetIndex();
     758        3457 :         if ( nStart < pNode->GetTxt().Len() )
     759             :         {
     760           0 :             lcl_SkipAttr( pNode, rIdx, nStart );
     761             :         }
     762        3457 :         sal_Unicode c = rStr.GetChar( nCnt );
     763        3457 :         if (GetIDocumentUndoRedo().DoesUndo())
     764             :         {
     765           0 :             bool bMerged(false);
     766           0 :             if (GetIDocumentUndoRedo().DoesGroupUndo())
     767             :             {
     768           0 :                 SwUndo *const pUndo = GetUndoManager().GetLastUndo();
     769             :                 SwUndoOverwrite *const pUndoOW(
     770           0 :                     dynamic_cast<SwUndoOverwrite *>(pUndo) );
     771           0 :                 if (pUndoOW)
     772             :                 {
     773             :                     // if CanGrouping() returns true it's already merged
     774           0 :                     bMerged = pUndoOW->CanGrouping( this, rPt, c );
     775             :                 }
     776             :             }
     777           0 :             if (!bMerged)
     778             :             {
     779           0 :                 SwUndo *const pUndoOW( new SwUndoOverwrite(this, rPt, c) );
     780           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndoOW);
     781             :             }
     782             :         }
     783             :         else
     784             :         {
     785             :             // start behind the characters (to fix the attributes!)
     786        3457 :             if( nStart < pNode->GetTxt().Len() )
     787           0 :                 ++rIdx;
     788        3457 :             pNode->InsertText( rtl::OUString(c), rIdx, INS_EMPTYEXPAND );
     789        3457 :             if( nStart+1 < rIdx.GetIndex() )
     790             :             {
     791           0 :                 rIdx = nStart;
     792           0 :                 pNode->EraseText( rIdx, 1 );
     793           0 :                 ++rIdx;
     794             :             }
     795             :         }
     796             :     }
     797         646 :     pNode->SetIgnoreDontExpand( bOldExpFlg );
     798             : 
     799         646 :     sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
     800         646 :                                 ? pNode->GetpSwpHints()->Count() : 0;
     801         646 :     if( nOldAttrCnt != nNewAttrCnt )
     802             :     {
     803           0 :         SwUpdateAttr aHint( 0, 0, 0 );
     804           0 :         pNode->ModifyBroadcast( 0, &aHint, TYPE( SwCrsrShell ) );
     805             :     }
     806             : 
     807        1770 :     if (!GetIDocumentUndoRedo().DoesUndo() &&
     808        1124 :         !IsIgnoreRedline() && !GetRedlineTbl().empty())
     809             :     {
     810         233 :         SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
     811         233 :         DeleteRedline( aPam, true, USHRT_MAX );
     812             :     }
     813         413 :     else if( IsRedlineOn() )
     814             :     {
     815             :         // FIXME: this redline is WRONG: there is no DELETE, and the skipped
     816             :         // characters are also included in aPam
     817          92 :         SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
     818          92 :         AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
     819             :     }
     820             : 
     821         646 :     SetModified();
     822         646 :     return sal_True;
     823             : }
     824             : 
     825           0 : bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
     826             : {
     827           0 :     SwNodeIndex aIdx( rPaM.Start()->nNode );
     828           0 :     sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
     829           0 :     sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
     830           0 :     aIdx--;             // in front of the move area!
     831             : 
     832           0 :     bool bRet = MoveRange( rPaM, rPos, eMvFlags );
     833           0 :     if( bRet && !bOneNode )
     834             :     {
     835           0 :         if( bJoinTxt )
     836           0 :             ++aIdx;
     837           0 :         SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
     838           0 :         SwNodeIndex aNxtIdx( aIdx );
     839           0 :         if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
     840             :         {
     841             :             {   // Block so SwIndex into node is deleted before Join
     842             :                 CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
     843           0 :                             pTxtNd->GetTxt().Len() ) ), 0, sal_True );
     844             :             }
     845           0 :             pTxtNd->JoinNext();
     846           0 :         }
     847             :     }
     848           0 :     return bRet;
     849             : }
     850             : 
     851             : // It seems that this is mostly used by SwDoc internals; the only
     852             : // way to call this from the outside seems to be the special case in
     853             : // SwDoc::CopyRange (but I have not managed to actually hit that case).
     854        2572 : bool SwDoc::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
     855             : {
     856             :     // nothing moved: return
     857        2572 :     const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
     858        2572 :     if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
     859        2572 :         return false;
     860             : 
     861             :     // Save the paragraph anchored Flys, so that they can be moved.
     862           0 :     _SaveFlyArr aSaveFlyArr;
     863           0 :     _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
     864             : 
     865             :     // save redlines (if DOC_MOVEREDLINES is used)
     866           0 :     _SaveRedlines aSaveRedl;
     867           0 :     if( DOC_MOVEREDLINES & eMvFlags && !GetRedlineTbl().empty() )
     868             :     {
     869           0 :         lcl_SaveRedlines( rPaM, aSaveRedl );
     870             : 
     871             :         // #i17764# unfortunately, code below relies on undos being
     872             :         //          in a particular order, and presence of bookmarks
     873             :         //          will change this order. Hence, we delete bookmarks
     874             :         //          here without undo.
     875           0 :         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
     876             :         _DelBookmarks(
     877             :             pStt->nNode,
     878             :             pEnd->nNode,
     879             :             NULL,
     880             :             &pStt->nContent,
     881           0 :             &pEnd->nContent);
     882             :     }
     883             : 
     884             : 
     885           0 :     int bUpdateFtn = sal_False;
     886           0 :     SwFtnIdxs aTmpFntIdx;
     887             : 
     888           0 :     SwUndoMove * pUndoMove = 0;
     889           0 :     if (GetIDocumentUndoRedo().DoesUndo())
     890             :     {
     891           0 :         GetIDocumentUndoRedo().ClearRedo();
     892           0 :         pUndoMove = new SwUndoMove( rPaM, rPos );
     893           0 :         pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
     894             :     }
     895             :     else
     896             :     {
     897             :         bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
     898           0 :                                     GetFtnIdxs(), aTmpFntIdx,
     899           0 :                                     &pStt->nContent, &pEnd->nContent );
     900             :     }
     901             : 
     902           0 :     sal_Bool bSplit = sal_False;
     903           0 :     SwPaM aSavePam( rPos, rPos );
     904             : 
     905             :     // Move the SPoint to the beginning of the range
     906           0 :     if( rPaM.GetPoint() == pEnd )
     907           0 :         rPaM.Exchange();
     908             : 
     909             :     // If there is a TextNode before and after the Move, create a JoinNext in the EditShell.
     910           0 :     SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
     911           0 :     sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
     912             : 
     913             :     // If one ore more TextNodes are moved, SwNodes::Move will do a SplitNode.
     914             :     // However, this does not update the cursor. So we create a TextNode to keep
     915             :     // updating the indices. After the Move the Node is optionally deleted.
     916           0 :     SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
     917           0 :     if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
     918           0 :         ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam  )) )
     919             :     {
     920           0 :         bSplit = sal_True;
     921           0 :         xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
     922             : 
     923           0 :         std::vector<sal_uLong> aBkmkArr;
     924           0 :         _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
     925           0 :                         aBkmkArr, SAVEFLY_SPLIT );
     926             : 
     927           0 :         pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
     928             : 
     929           0 :         if( !aBkmkArr.empty() )
     930           0 :             _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, true );
     931             : 
     932             :         // correct the PaM!
     933           0 :         if( rPos.nNode == rPaM.GetMark()->nNode )
     934             :         {
     935           0 :             rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
     936           0 :             rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
     937           0 :         }
     938             :     }
     939             : 
     940             :     // Put back the Pam by one "content"; so that it's always outside of
     941             :     // the manipulated range.
     942             :     // If there's no content anymore, set it to the StartNode (that's
     943             :     // always there).
     944           0 :     sal_Bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
     945           0 :     if( bNullCntnt )
     946             :     {
     947           0 :         aSavePam.GetPoint()->nNode--;
     948             :     }
     949             : 
     950             :     // Copy all Bookmarks that are within the Move range into an array,
     951             :     // that saves the positon as an offset.
     952           0 :     ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
     953             :     _DelBookmarks(
     954             :         pStt->nNode,
     955             :         pEnd->nNode,
     956             :         &aSaveBkmks,
     957             :         &pStt->nContent,
     958           0 :         &pEnd->nContent);
     959             : 
     960             :     // If there is no range anymore due to the above deletions (e.g. the
     961             :     // footnotes got deleted), it's still a valid Move!
     962           0 :     if( *rPaM.GetPoint() != *rPaM.GetMark() )
     963             :     {
     964             :         // now do the actual move
     965           0 :         GetNodes().MoveRange( rPaM, rPos, GetNodes() );
     966             : 
     967             :         // after a MoveRange() the Mark is deleted
     968           0 :         if ( rPaM.HasMark() ) // => no Move occurred!
     969             :         {
     970           0 :             delete pUndoMove;
     971           0 :             return false;
     972             :         }
     973             :     }
     974             :     else
     975           0 :         rPaM.DeleteMark();
     976             : 
     977             :     OSL_ENSURE( *aSavePam.GetMark() == rPos ||
     978             :             ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
     979             :             "PaM was not moved. Aren't there ContentNodes at the beginning/end?" );
     980           0 :     *aSavePam.GetMark() = rPos;
     981             : 
     982           0 :     rPaM.SetMark();         // create a Sel. around the new range
     983           0 :     pTNd = aSavePam.GetNode()->GetTxtNode();
     984           0 :     if (GetIDocumentUndoRedo().DoesUndo())
     985             :     {
     986             :         // correct the SavePam's Content first
     987           0 :         if( bNullCntnt )
     988             :         {
     989           0 :             aSavePam.GetPoint()->nContent = 0;
     990             :         }
     991             : 
     992             :         // The method SwEditShell::Move() merges the TextNode after the Move,
     993             :         // where the rPaM is located.
     994             :         // If the Content was moved to the back and the SavePam's SPoint is
     995             :         // in the next Node, we have to deal with this when saving the Undo object!
     996           0 :         SwTxtNode * pPamTxtNd = 0;
     997             : 
     998             :         // Is passed to SwUndoMove, which happens when subsequently calling Undo JoinNext.
     999             :         // If it's not possible to call Undo JoinNext here.
    1000           0 :         sal_Bool bJoin = bSplit && pTNd;
    1001             :         bCorrSavePam = bCorrSavePam &&
    1002           0 :                         0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
    1003           0 :                         && pPamTxtNd->CanJoinNext()
    1004           0 :                         && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
    1005             : 
    1006             :         // Do two Nodes have to be joined at the SavePam?
    1007           0 :         if( bJoin && pTNd->CanJoinNext() )
    1008             :         {
    1009           0 :             pTNd->JoinNext();
    1010             :             // No temporary Index when using &&.
    1011             :             // We probably only want to compare the indices.
    1012           0 :             if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
    1013           0 :                                 aSavePam.GetPoint()->nNode.GetIndex() )
    1014             :             {
    1015           0 :                 aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
    1016             :             }
    1017           0 :             bJoin = sal_False;
    1018             :         }
    1019           0 :         else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
    1020             :         {
    1021           0 :             aSavePam.GetPoint()->nNode++;
    1022             :         }
    1023             : 
    1024             :         // The newly inserted range is now inbetween SPoint and GetMark.
    1025           0 :         pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
    1026           0 :                                     bJoin, bCorrSavePam );
    1027           0 :         GetIDocumentUndoRedo().AppendUndo( pUndoMove );
    1028             :     }
    1029             :     else
    1030             :     {
    1031           0 :         bool bRemove = true;
    1032             :         // Do two Nodes have to be joined at the SavePam?
    1033           0 :         if( bSplit && pTNd )
    1034             :         {
    1035           0 :             if( pTNd->CanJoinNext())
    1036             :             {
    1037             :                 // Always join next, because <pTNd> has to stay as it is.
    1038             :                 // A join previous from its next would more or less delete <pTNd>
    1039           0 :                 pTNd->JoinNext();
    1040           0 :                 bRemove = false;
    1041             :             }
    1042             :         }
    1043           0 :         if( bNullCntnt )
    1044             :         {
    1045           0 :             aSavePam.GetPoint()->nNode++;
    1046           0 :             aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
    1047             :         }
    1048           0 :         else if( bRemove ) // No move forward after joining with next paragraph
    1049             :         {
    1050           0 :             aSavePam.Move( fnMoveForward, fnGoCntnt );
    1051             :         }
    1052             :     }
    1053             : 
    1054             :     // Insert the Bookmarks back into the Document.
    1055           0 :     *rPaM.GetMark() = *aSavePam.Start();
    1056           0 :     for(
    1057           0 :         ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
    1058           0 :         pBkmk != aSaveBkmks.end();
    1059             :         ++pBkmk)
    1060             :         pBkmk->SetInDoc(
    1061             :             this,
    1062           0 :             rPaM.GetMark()->nNode,
    1063           0 :             &rPaM.GetMark()->nContent);
    1064           0 :     *rPaM.GetPoint() = *aSavePam.End();
    1065             : 
    1066             :     // Move the Flys to the new position.
    1067           0 :     _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
    1068             : 
    1069             :     // restore redlines (if DOC_MOVEREDLINES is used)
    1070           0 :     if( !aSaveRedl.empty() )
    1071             :     {
    1072           0 :         lcl_RestoreRedlines( this, *aSavePam.Start(), aSaveRedl );
    1073             :     }
    1074             : 
    1075           0 :     if( bUpdateFtn )
    1076             :     {
    1077           0 :         if( !aTmpFntIdx.empty() )
    1078             :         {
    1079           0 :             GetFtnIdxs().insert( aTmpFntIdx );
    1080           0 :             aTmpFntIdx.clear();
    1081             :         }
    1082             : 
    1083           0 :         GetFtnIdxs().UpdateAllFtn();
    1084             :     }
    1085             : 
    1086           0 :     SetModified();
    1087           0 :     return true;
    1088             : }
    1089             : 
    1090           0 : bool SwDoc::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
    1091             :         SwMoveFlags eMvFlags )
    1092             : {
    1093             :     // Moves all Nodes to the new position.
    1094             :     // Bookmarks are moved too (currently without Undo support).
    1095             : 
    1096             :     // If footnotes are being moved to the special section, remove them now.
    1097             :     //
    1098             :     // Or else delete the Frames for all footnotes that are being moved
    1099             :     // and have it rebuild after the Move (footnotes can change pages).
    1100             :     // Additionally we have to correct the FtnIdx array's sorting.
    1101           0 :     int bUpdateFtn = sal_False;
    1102           0 :     SwFtnIdxs aTmpFntIdx;
    1103             : 
    1104           0 :     SwUndoMove* pUndo = 0;
    1105           0 :     if ((DOC_CREATEUNDOOBJ & eMvFlags ) && GetIDocumentUndoRedo().DoesUndo())
    1106             :     {
    1107           0 :         pUndo = new SwUndoMove( this, rRange, rPos );
    1108             :     }
    1109             :     else
    1110             :     {
    1111             :         bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
    1112           0 :                                     GetFtnIdxs(), aTmpFntIdx );
    1113             :     }
    1114             : 
    1115           0 :     _SaveRedlines aSaveRedl;
    1116           0 :     std::vector<SwRedline*> aSavRedlInsPosArr;
    1117           0 :     if( DOC_MOVEREDLINES & eMvFlags && !GetRedlineTbl().empty() )
    1118             :     {
    1119           0 :         lcl_SaveRedlines( rRange, aSaveRedl );
    1120             : 
    1121             :         // Find all RedLines that end at the InsPos.
    1122             :         // These have to be moved back to the "old" position after the Move.
    1123           0 :         sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode(), USHRT_MAX );
    1124           0 :         if( USHRT_MAX != nRedlPos )
    1125             :         {
    1126             :             const SwPosition *pRStt, *pREnd;
    1127           0 :             do {
    1128           0 :                 SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
    1129           0 :                 pRStt = pTmp->Start();
    1130           0 :                 pREnd = pTmp->End();
    1131           0 :                 if( pREnd->nNode == rPos && pRStt->nNode < rPos )
    1132             :                 {
    1133           0 :                     aSavRedlInsPosArr.push_back( pTmp );
    1134             :                 }
    1135           0 :             } while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().size());
    1136             :         }
    1137             :     }
    1138             : 
    1139             :     // Copy all Bookmarks that are within the Move range into an array
    1140             :     // that stores all references to positions as an offset.
    1141             :     // The final mapping happens after the Move.
    1142           0 :     ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
    1143           0 :     _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
    1144             : 
    1145             :     // Save the paragraph-bound Flys, so that they can be moved.
    1146           0 :     _SaveFlyArr aSaveFlyArr;
    1147           0 :     if( !GetSpzFrmFmts()->empty() )
    1148           0 :         _SaveFlyInRange( rRange, aSaveFlyArr );
    1149             : 
    1150             :     // Set it to before the Position, so that it cannot be moved further.
    1151           0 :     SwNodeIndex aIdx( rPos, -1 );
    1152             : 
    1153           0 :     SwNodeIndex* pSaveInsPos = 0;
    1154           0 :     if( pUndo )
    1155           0 :         pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
    1156             : 
    1157             :     // move the Nodes
    1158           0 :     sal_Bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
    1159           0 :     if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos, !bNoDelFrms ) )
    1160             :     {
    1161           0 :         ++aIdx;     // again back to old position
    1162           0 :         if( pSaveInsPos )
    1163           0 :             ++(*pSaveInsPos);
    1164             :     }
    1165             :     else
    1166             :     {
    1167           0 :         aIdx = rRange.aStart;
    1168           0 :         delete pUndo, pUndo = 0;
    1169             :     }
    1170             : 
    1171             :     // move the Flys to the new position
    1172           0 :     if( !aSaveFlyArr.empty() )
    1173           0 :         _RestFlyInRange( aSaveFlyArr, aIdx, NULL );
    1174             : 
    1175             :     // Add the Bookmarks back to the Document
    1176           0 :     for(
    1177           0 :         ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
    1178           0 :         pBkmk != aSaveBkmks.end();
    1179             :         ++pBkmk)
    1180           0 :         pBkmk->SetInDoc(this, aIdx);
    1181             : 
    1182           0 :     if( !aSavRedlInsPosArr.empty() )
    1183             :     {
    1184           0 :         SwNode* pNewNd = &aIdx.GetNode();
    1185           0 :         for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.size(); ++n )
    1186             :         {
    1187           0 :             SwRedline* pTmp = aSavRedlInsPosArr[ n ];
    1188           0 :             if( GetRedlineTbl().Contains( pTmp ) )
    1189             :             {
    1190           0 :                 SwPosition* pEnd = pTmp->End();
    1191           0 :                 pEnd->nNode = aIdx;
    1192           0 :                 pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
    1193             :             }
    1194             :         }
    1195             :     }
    1196             : 
    1197           0 :     if( !aSaveRedl.empty() )
    1198           0 :         lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
    1199             : 
    1200           0 :     if( pUndo )
    1201             :     {
    1202           0 :         pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
    1203           0 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
    1204             :     }
    1205             : 
    1206           0 :     delete pSaveInsPos;
    1207             : 
    1208           0 :     if( bUpdateFtn )
    1209             :     {
    1210           0 :         if( !aTmpFntIdx.empty() )
    1211             :         {
    1212           0 :             GetFtnIdxs().insert( aTmpFntIdx );
    1213           0 :             aTmpFntIdx.clear();
    1214             :         }
    1215             : 
    1216           0 :         GetFtnIdxs().UpdateAllFtn();
    1217             :     }
    1218             : 
    1219           0 :     SetModified();
    1220           0 :     return sal_True;
    1221             : }
    1222             : 
    1223             : // Convert list of ranges of whichIds to a corresponding list of whichIds
    1224          88 : static std::vector<sal_uInt16> * lcl_RangesToVector(sal_uInt16 * pRanges)
    1225             : {
    1226          88 :     std::vector<sal_uInt16> * pResult = new std::vector<sal_uInt16>();
    1227             : 
    1228          88 :     int i = 0;
    1229         352 :     while (pRanges[i] != 0)
    1230             :     {
    1231             :         OSL_ENSURE(pRanges[i+1] != 0, "malformed ranges");
    1232             : 
    1233        3608 :         for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
    1234        3432 :             pResult->push_back(j);
    1235             : 
    1236         176 :         i += 2;
    1237             :     }
    1238             : 
    1239          88 :     return pResult;
    1240             : }
    1241             : 
    1242         761 : static bool lcl_StrLenOverFlow( const SwPaM& rPam )
    1243             : {
    1244             :     // If we try to merge two paragraph we have to test if afterwards
    1245             :     // the string doesn't exceed the allowed string length
    1246         761 :     bool bRet = false;
    1247         761 :     if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
    1248             :     {
    1249         268 :         const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
    1250         268 :         const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
    1251         268 :         if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
    1252             :         {
    1253         268 :             sal_uInt64 nSum = pStt->nContent.GetIndex() +
    1254         268 :                 pEndNd->GetTxt().Len() - pEnd->nContent.GetIndex();
    1255         268 :             if( nSum > STRING_LEN )
    1256           0 :                 bRet = true;
    1257             :         }
    1258             :     }
    1259         761 :     return bRet;
    1260             : }
    1261             : 
    1262         543 : void sw_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
    1263             : {
    1264         543 :     rJoinTxt = sal_False;
    1265         543 :     rJoinPrev = sal_False;
    1266         543 :     if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
    1267             :     {
    1268         268 :         const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
    1269         268 :         SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
    1270         268 :         if( pSttNd )
    1271             :         {
    1272         268 :             SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
    1273         268 :             rJoinTxt = 0 != pEndNd;
    1274         268 :             if( rJoinTxt )
    1275             :             {
    1276         268 :                 bool bExchange = pStt == rPam.GetPoint();
    1277         357 :                 if( !pStt->nContent.GetIndex() &&
    1278          89 :                     pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex() )
    1279           1 :                     bExchange = !bExchange;
    1280         268 :                 if( bExchange )
    1281         267 :                     rPam.Exchange();
    1282         268 :                 rJoinPrev = rPam.GetPoint() == pStt;
    1283             :                 OSL_ENSURE( !pStt->nContent.GetIndex() &&
    1284             :                     pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex()
    1285             :                     ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
    1286             :                     : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
    1287             :                     "sw_GetJoinFlags");
    1288             :             }
    1289             :         }
    1290             :     }
    1291         543 : }
    1292             : 
    1293         268 : void sw_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
    1294             : {
    1295         268 :     SwNodeIndex aIdx( rPam.GetPoint()->nNode );
    1296         268 :     SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
    1297         268 :     SwNodeIndex aOldIdx( aIdx );
    1298         268 :     SwTxtNode *pOldTxtNd = pTxtNd;
    1299             : 
    1300         268 :     if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
    1301             :     {
    1302         268 :         SwDoc* pDoc = rPam.GetDoc();
    1303         268 :         if( bJoinPrev )
    1304             :         {
    1305             :             // We do not need to handle xmlids in this case, because
    1306             :             // it is only invoked if one paragraph is completely empty
    1307             :             // (see sw_GetJoinFlags)
    1308             :             {
    1309             :                 // If PageBreaks are deleted/set, it must not be added to the Undo history!
    1310             :                 // Also, deleteing the Node is not added to the Undo histroy!
    1311           1 :                 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
    1312             : 
    1313             :                 /* PageBreaks, PageDesc, ColumnBreaks */
    1314             :                 // If we need to change something about the logic to copy the PageBreaks,
    1315             :                 // PageDesc, etc. we also have to change SwUndoDelete.
    1316             :                 // There, we copy the AUTO PageBreak from the GetMarkNode!
    1317             : 
    1318             :                 /* The GetMarkNode */
    1319           1 :                 if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
    1320             :                 {
    1321             :                     const SfxPoolItem* pItem;
    1322           0 :                     if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
    1323           0 :                         RES_BREAK, sal_False, &pItem ) )
    1324           0 :                         pTxtNd->ResetAttr( RES_BREAK );
    1325           0 :                     if( pTxtNd->HasSwAttrSet() &&
    1326           0 :                         SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
    1327           0 :                         RES_PAGEDESC, sal_False, &pItem ) )
    1328           0 :                         pTxtNd->ResetAttr( RES_PAGEDESC );
    1329             :                 }
    1330             : 
    1331             :                 /* The PointNode */
    1332           1 :                 if( pOldTxtNd->HasSwAttrSet() )
    1333             :                 {
    1334             :                     const SfxPoolItem* pItem;
    1335           0 :                     SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
    1336           0 :                     const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
    1337           0 :                     if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
    1338           0 :                         sal_False, &pItem ) )
    1339           0 :                         aSet.Put( *pItem );
    1340           0 :                     if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
    1341           0 :                         sal_False, &pItem ) )
    1342           0 :                         aSet.Put( *pItem );
    1343           0 :                     if( aSet.Count() )
    1344           0 :                         pTxtNd->SetAttr( aSet );
    1345             :                 }
    1346           1 :                 pOldTxtNd->FmtToTxtAttr( pTxtNd );
    1347             : 
    1348           1 :                 std::vector<sal_uLong> aBkmkArr;
    1349             :                 ::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
    1350           1 :                                     pOldTxtNd->Len(), aBkmkArr );
    1351             : 
    1352           1 :                 SwIndex aAlphaIdx(pTxtNd);
    1353           1 :                 pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
    1354           2 :                                     pOldTxtNd->Len() );
    1355           1 :                 SwPosition aAlphaPos( aIdx, aAlphaIdx );
    1356           1 :                 pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
    1357             : 
    1358             :                 // move all Bookmarks/TOXMarks
    1359           1 :                 if( !aBkmkArr.empty() )
    1360           0 :                     ::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
    1361             : 
    1362             :                 // If the passed PaM is not in the Crsr ring,
    1363             :                 // treat it seperately (e.g. when it's being called from AutoFormat)
    1364           1 :                 if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
    1365           0 :                     rPam.GetBound( sal_True ) = aAlphaPos;
    1366           1 :                 if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
    1367           0 :                     rPam.GetBound( sal_False ) = aAlphaPos;
    1368             :             }
    1369             :             // delete the Node, at last!
    1370           1 :             pDoc->GetNodes().Delete( aOldIdx, 1 );
    1371             :         }
    1372             :         else
    1373             :         {
    1374         267 :             SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
    1375         267 :             if( pTxtNd->Len() )
    1376         179 :                 pDelNd->FmtToTxtAttr( pTxtNd );
    1377             :             else
    1378             :             {
    1379             :                 /* This case was missed:
    1380             : 
    1381             :                    <something></something>   <-- pTxtNd
    1382             :                    <other>ccc</other>        <-- pDelNd
    1383             : 
    1384             :                    <something> and <other> are paragraph
    1385             :                    attributes. The attribute <something> stayed if not
    1386             :                    overwritten by an attribute in "ccc". Fixed by
    1387             :                    first resetting all character attributes in first
    1388             :                    paragraph (pTxtNd).
    1389             :                 */
    1390             :                 std::vector<sal_uInt16> * pShorts =
    1391          88 :                     lcl_RangesToVector(aCharFmtSetRange);
    1392          88 :                 pTxtNd->ResetAttr(*pShorts);
    1393          88 :                 delete pShorts;
    1394             : 
    1395          88 :                 if( pDelNd->HasSwAttrSet() )
    1396             :                 {
    1397             :                     // only copy the character attributes
    1398          13 :                     SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
    1399          13 :                     aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
    1400          13 :                     pTxtNd->SetAttr( aTmpSet );
    1401             :                 }
    1402             :             }
    1403             : 
    1404         267 :             pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
    1405             :             // #i100466# adjust given <rPam>, if it does not belong to the cursors
    1406         267 :             if ( pDelNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
    1407             :             {
    1408           0 :                 rPam.GetBound( sal_True ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
    1409             :             }
    1410         267 :             if( pDelNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
    1411             :             {
    1412           0 :                 rPam.GetBound( sal_False ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
    1413             :             }
    1414         267 :             pTxtNd->JoinNext();
    1415             :         }
    1416         268 :     }
    1417         268 : }
    1418             : 
    1419             : static void
    1420        1159 : lcl_CalcBreaks( ::std::vector<xub_StrLen> & rBreaks, SwPaM const & rPam )
    1421             : {
    1422             :     SwTxtNode const * const pTxtNode(
    1423        1159 :             rPam.End()->nNode.GetNode().GetTxtNode() );
    1424        1159 :     if (!pTxtNode)
    1425         415 :         return; // left-overlap only possible at end of selection...
    1426             : 
    1427         744 :     const xub_StrLen nStart(rPam.Start()->nContent.GetIndex());
    1428         744 :     const xub_StrLen nEnd  (rPam.End  ()->nContent.GetIndex());
    1429         744 :     if (nEnd == pTxtNode->Len())
    1430         733 :         return; // paragraph selected until the end
    1431             : 
    1432          27 :     for (xub_StrLen i = nStart; i < nEnd; ++i)
    1433             :     {
    1434          16 :         const sal_Unicode c(pTxtNode->GetTxt().GetChar(i));
    1435          16 :         if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
    1436             :         {
    1437           3 :             SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
    1438           3 :             if (pAttr && pAttr->GetEnd() && (*pAttr->GetEnd() > nEnd))
    1439             :             {
    1440             :                 OSL_ENSURE(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
    1441           0 :                 rBreaks.push_back(i);
    1442             :             }
    1443             :         }
    1444             :     }
    1445             : }
    1446             : 
    1447        1159 : static bool lcl_DoWithBreaks(SwDoc & rDoc, SwPaM & rPam,
    1448             :         bool (SwDoc::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
    1449             : {
    1450        1159 :     ::std::vector<xub_StrLen> Breaks;
    1451             : 
    1452        1159 :     lcl_CalcBreaks(Breaks, rPam);
    1453             : 
    1454        1159 :     if (!Breaks.size())
    1455             :     {
    1456        1159 :         return (rDoc.*pFunc)(rPam, bForceJoinNext);
    1457             :     }
    1458             : 
    1459             :     // Deletion must be split into several parts if the text node
    1460             :     // contains a text attribute with end and with dummy character
    1461             :     // and the selection does not contain the text attribute completely,
    1462             :     // but overlaps its start (left), where the dummy character is.
    1463             : 
    1464           0 :     SwPosition const & rSelectionEnd( *rPam.End() );
    1465             : 
    1466           0 :     bool bRet( true );
    1467             :     // iterate from end to start, to avoid invalidating the offsets!
    1468           0 :     ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
    1469           0 :     SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
    1470           0 :     SwPosition & rEnd( *aPam.End() );
    1471           0 :     SwPosition & rStart( *aPam.Start() );
    1472             : 
    1473           0 :     while (iter != Breaks.rend())
    1474             :     {
    1475           0 :         rStart.nContent = *iter + 1;
    1476           0 :         if (rEnd.nContent > rStart.nContent) // check if part is empty
    1477             :         {
    1478           0 :             bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
    1479             :         }
    1480           0 :         rEnd.nContent = *iter;
    1481           0 :         ++iter;
    1482             :     }
    1483             : 
    1484           0 :     rStart = *rPam.Start(); // set to original start
    1485           0 :     if (rEnd.nContent > rStart.nContent) // check if part is empty
    1486             :     {
    1487           0 :         bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
    1488             :     }
    1489             : 
    1490           0 :     return bRet;
    1491             : }
    1492             : 
    1493         218 : bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
    1494             : {
    1495             :     OSL_ENSURE( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
    1496             : 
    1497             :     {
    1498         218 :         SwUndoRedlineDelete* pUndo = 0;
    1499         218 :         RedlineMode_t eOld = GetRedlineMode();
    1500         218 :         checkRedlining(eOld);
    1501         218 :         if (GetIDocumentUndoRedo().DoesUndo())
    1502             :         {
    1503             : 
    1504             :     /* please don't translate -- for cultural reasons this comment is protected
    1505             :        until the redline implementation is finally fixed some day */
    1506             : //JP 06.01.98: MUSS noch optimiert werden!!!
    1507             :     SetRedlineMode(
    1508           0 :            (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
    1509             : 
    1510           0 :             GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
    1511           0 :             pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
    1512           0 :             GetIDocumentUndoRedo().AppendUndo(pUndo);
    1513             :         }
    1514         218 :         if( *rPam.GetPoint() != *rPam.GetMark() )
    1515           2 :             AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true);
    1516         218 :         SetModified();
    1517             : 
    1518         218 :         if( pUndo )
    1519             :         {
    1520           0 :             GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
    1521             :             // ??? why the hell is the AppendUndo not below the
    1522             :             // CanGrouping, so this hideous cleanup wouldn't be necessary?
    1523             :             // bah, this is redlining, probably changing this would break it...
    1524           0 :             if (GetIDocumentUndoRedo().DoesGroupUndo())
    1525             :             {
    1526           0 :                 SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
    1527             :                 SwUndoRedlineDelete *const pUndoRedlineDel(
    1528           0 :                         dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) );
    1529           0 :                 if (pUndoRedlineDel)
    1530             :                 {
    1531           0 :                     bool const bMerged = pUndoRedlineDel->CanGrouping(*pUndo);
    1532           0 :                     if (bMerged)
    1533             :                     {
    1534           0 :                         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
    1535             :                         SwUndo const*const pDeleted =
    1536           0 :                             GetUndoManager().RemoveLastUndo();
    1537             :                         OSL_ENSURE(pDeleted == pUndo,
    1538             :                             "DeleteAndJoinWithRedlineImpl: "
    1539             :                             "undo removed is not undo inserted?");
    1540           0 :                         delete pDeleted;
    1541             :                     }
    1542             :                 }
    1543             :             }
    1544             : //JP 06.01.98: MUSS noch optimiert werden!!!
    1545           0 : SetRedlineMode( eOld );
    1546             :         }
    1547         218 :         return true;
    1548             :     }
    1549             : }
    1550             : 
    1551         543 : bool SwDoc::DeleteAndJoinImpl( SwPaM & rPam,
    1552             :                                const bool bForceJoinNext )
    1553             : {
    1554             :     sal_Bool bJoinTxt, bJoinPrev;
    1555         543 :     sw_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
    1556             :     // #i100466#
    1557         543 :     if ( bForceJoinNext )
    1558             :     {
    1559           1 :         bJoinPrev = sal_False;
    1560             :     }
    1561             : 
    1562             :     {
    1563         543 :         bool const bSuccess( DeleteRangeImpl( rPam ) );
    1564         543 :         if (!bSuccess)
    1565         240 :             return false;
    1566             :     }
    1567             : 
    1568         303 :     if( bJoinTxt )
    1569             :     {
    1570         268 :         sw_JoinText( rPam, bJoinPrev );
    1571             :     }
    1572             : 
    1573         303 :     return true;
    1574             : }
    1575             : 
    1576         941 : bool SwDoc::DeleteRangeImpl(SwPaM & rPam, const bool)
    1577             : {
    1578             :     // Move all cursors out of the deleted range, but first copy the
    1579             :     // passed PaM, because it could be a cursor that would be moved!
    1580         941 :     SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
    1581         941 :     ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
    1582             : 
    1583         941 :     bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
    1584         941 :     if (bSuccess)
    1585             :     {   // now copy position from temp copy to given PaM
    1586         304 :         *rPam.GetPoint() = *aDelPam.GetPoint();
    1587             :     }
    1588             : 
    1589         941 :     return bSuccess;
    1590             : }
    1591             : 
    1592         941 : bool SwDoc::DeleteRangeImplImpl(SwPaM & rPam)
    1593             : {
    1594         941 :     SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
    1595             : 
    1596         941 :     if( !rPam.HasMark() || *pStt >= *pEnd )
    1597         637 :         return false;
    1598             : 
    1599         304 :     if( pACEWord )
    1600             :     {
    1601             :         // if necessary the saved Word for the exception
    1602           0 :         if( pACEWord->IsDeleted() ||  pStt->nNode != pEnd->nNode ||
    1603           0 :             pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
    1604           0 :             !pACEWord->CheckDelChar( *pStt ))
    1605           0 :             delete pACEWord, pACEWord = 0;
    1606             :     }
    1607             : 
    1608             :     {
    1609             :         // Delete all empty TextHints at the Mark's position
    1610         304 :         SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
    1611             :         SwpHints* pHts;
    1612         304 :         if( pTxtNd &&  0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
    1613             :         {
    1614             :             const xub_StrLen *pEndIdx;
    1615         143 :             xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
    1616         322 :             for( sal_uInt16 n = pHts->Count(); n; )
    1617             :             {
    1618         161 :                 const SwTxtAttr* pAttr = (*pHts)[ --n ];
    1619         161 :                 if( nMkCntPos > *pAttr->GetStart() )
    1620         125 :                     break;
    1621             : 
    1622          60 :                 if( nMkCntPos == *pAttr->GetStart() &&
    1623             :                     0 != (pEndIdx = pAttr->GetEnd()) &&
    1624          24 :                     *pEndIdx == *pAttr->GetStart() )
    1625          15 :                     pTxtNd->DestroyAttr( pHts->Cut( n ) );
    1626             :             }
    1627             :         }
    1628             :     }
    1629             : 
    1630             :     // Delete fieldmarks before postits, but let's leave them alone during import.
    1631         304 :     if (GetIDocumentUndoRedo().DoesUndo() && pStt->nNode == pEnd->nNode && (pEnd->nContent.GetIndex() - pStt->nContent.GetIndex()) == 1)
    1632             :     {
    1633           0 :         SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
    1634           0 :         xub_StrLen nIndex = rPam.Start()->nContent.GetIndex();
    1635             :         // We may have a postit here.
    1636           0 :         if (pTxtNd->GetTxt().GetChar(nIndex) == CH_TXTATR_INWORD)
    1637             :         {
    1638           0 :             SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(nIndex, RES_TXTATR_FIELD);
    1639           0 :             if (pTxtAttr && pTxtAttr->GetFld().GetFld()->Which() == RES_POSTITFLD)
    1640             :             {
    1641           0 :                 const SwPostItField* pField = dynamic_cast<const SwPostItField*>(pTxtAttr->GetFld().GetFld());
    1642           0 :                 IDocumentMarkAccess::const_iterator_t ppMark = getIDocumentMarkAccess()->findMark(pField->GetName());
    1643           0 :                 if (ppMark != getIDocumentMarkAccess()->getMarksEnd())
    1644           0 :                     getIDocumentMarkAccess()->deleteMark(ppMark);
    1645             :             }
    1646             :         }
    1647             :     }
    1648             : 
    1649             :     {
    1650             :         // Send DataChanged before deletion, so that we still know
    1651             :         // which objects are in the range.
    1652             :         // Afterwards they could be before/after the Position.
    1653         304 :         SwDataChanged aTmp( rPam );
    1654             :     }
    1655             : 
    1656             : 
    1657         304 :     if (GetIDocumentUndoRedo().DoesUndo())
    1658             :     {
    1659           0 :         GetIDocumentUndoRedo().ClearRedo();
    1660           0 :         bool bMerged(false);
    1661           0 :         if (GetIDocumentUndoRedo().DoesGroupUndo())
    1662             :         {
    1663           0 :             SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
    1664             :             SwUndoDelete *const pUndoDelete(
    1665           0 :                     dynamic_cast<SwUndoDelete *>(pLastUndo) );
    1666           0 :             if (pUndoDelete)
    1667             :             {
    1668           0 :                 bMerged = pUndoDelete->CanGrouping( this, rPam );
    1669             :                 // if CanGrouping() returns true it's already merged
    1670             :             }
    1671             :         }
    1672           0 :         if (!bMerged)
    1673             :         {
    1674           0 :             GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
    1675             :         }
    1676             : 
    1677           0 :         SetModified();
    1678             : 
    1679           0 :         return true;
    1680             :     }
    1681             : 
    1682         304 :     if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
    1683           4 :         DeleteRedline( rPam, true, USHRT_MAX );
    1684             : 
    1685             :     // Delete and move all "Flys at the paragraph", which are within the Selection
    1686         304 :     DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
    1687             :     _DelBookmarks(
    1688             :         pStt->nNode,
    1689             :         pEnd->nNode,
    1690             :         NULL,
    1691             :         &pStt->nContent,
    1692         304 :         &pEnd->nContent);
    1693             : 
    1694         304 :     SwNodeIndex aSttIdx( pStt->nNode );
    1695         304 :     SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
    1696             : 
    1697             :     do {        // middle checked loop!
    1698         304 :         if( pCNd )
    1699             :         {
    1700         304 :             SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
    1701         304 :             if ( pStartTxtNode )
    1702             :             {
    1703             :                 // now move the Content to the new Node
    1704         304 :                 sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
    1705          36 :                 xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
    1706         268 :                                            : pCNd->Len() )
    1707         608 :                                         - pStt->nContent.GetIndex();
    1708             : 
    1709             :                 // Don't call again, if already empty
    1710         304 :                 if( nLen )
    1711             :                 {
    1712          49 :                     pStartTxtNode->EraseText( pStt->nContent, nLen );
    1713             : 
    1714          49 :                     if( !pStartTxtNode->Len() )
    1715             :                     {
    1716             :                 // METADATA: remove reference if empty (consider node deleted)
    1717          33 :                         pStartTxtNode->RemoveMetadataReference();
    1718             :                     }
    1719             :                 }
    1720             : 
    1721         304 :                 if( bOneNd )        // that's it
    1722          36 :                     break;
    1723             : 
    1724         268 :                 ++aSttIdx;
    1725             :             }
    1726             :             else
    1727             :             {
    1728             :                 // So that there are no indices left registered when deleted,
    1729             :                 // we remove a SwPaM from the Content here.
    1730           0 :                 pStt->nContent.Assign( 0, 0 );
    1731             :             }
    1732             :         }
    1733             : 
    1734         268 :         pCNd = pEnd->nNode.GetNode().GetCntntNode();
    1735         268 :         if( pCNd )
    1736             :         {
    1737         268 :             SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
    1738         268 :             if( pEndTxtNode )
    1739             :             {
    1740             :                 // if already empty, don't call again
    1741         268 :                 if( pEnd->nContent.GetIndex() )
    1742             :                 {
    1743           1 :                     SwIndex aIdx( pCNd, 0 );
    1744           1 :                     pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
    1745             : 
    1746           1 :                     if( !pEndTxtNode->Len() )
    1747             :                     {
    1748             :                 // METADATA: remove reference if empty (consider node deleted)
    1749           1 :                         pEndTxtNode->RemoveMetadataReference();
    1750           1 :                     }
    1751             :                 }
    1752             :             }
    1753             :             else
    1754             :             {
    1755             :                 // So that there are no indices left registered when deleted,
    1756             :                 // we remove a SwPaM from the Content here.
    1757           0 :                 pEnd->nContent.Assign( 0, 0 );
    1758             :             }
    1759             :         }
    1760             : 
    1761             :         // if the end is not a content node, delete it as well
    1762         268 :         sal_uInt32 nEnde = pEnd->nNode.GetIndex();
    1763         268 :         if( pCNd == NULL )
    1764           0 :             nEnde++;
    1765             : 
    1766         268 :         if( aSttIdx != nEnde )
    1767             :         {
    1768             :             // delete the Nodes into the NodesArary
    1769           6 :             GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
    1770             :         }
    1771             : 
    1772             :         // If the Node that contained the Cursor has been deleted,
    1773             :         // the Content has to be assigned to the current Content.
    1774         268 :         pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
    1775         536 :                                 pStt->nContent.GetIndex() );
    1776             : 
    1777             :         // If we deleted across Node boundaries we have to correct the PaM,
    1778             :         // because they are in different Nodes now.
    1779             :         // Also, the Selection is revoked.
    1780         268 :         *pEnd = *pStt;
    1781         268 :         rPam.DeleteMark();
    1782             : 
    1783             :     } while( sal_False );
    1784             : 
    1785         304 :     if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
    1786           4 :         CompressRedlines();
    1787         304 :     SetModified();
    1788             : 
    1789         304 :     return true;
    1790             : }
    1791             : 
    1792             : // #i100466# Add handling of new optional parameter <bForceJoinNext>
    1793         761 : bool SwDoc::DeleteAndJoin( SwPaM & rPam,
    1794             :                            const bool bForceJoinNext )
    1795             : {
    1796         761 :     if ( lcl_StrLenOverFlow( rPam ) )
    1797           0 :         return false;
    1798             : 
    1799         761 :     return lcl_DoWithBreaks( *this, rPam, (IsRedlineOn())
    1800             :                 ? &SwDoc::DeleteAndJoinWithRedlineImpl
    1801             :                 : &SwDoc::DeleteAndJoinImpl,
    1802        1522 :                 bForceJoinNext );
    1803             : }
    1804             : 
    1805         398 : bool SwDoc::DeleteRange( SwPaM & rPam )
    1806             : {
    1807         398 :     return lcl_DoWithBreaks( *this, rPam, &SwDoc::DeleteRangeImpl );
    1808             : }
    1809             : 
    1810             : 
    1811           0 : static void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
    1812             :     xub_StrLen /*nBeginGrammarCheck*/, const ModelToViewHelper &rConversionMap )
    1813             : {
    1814           0 :     if( rTxtNode.IsGrammarCheckDirty() )
    1815           0 :         return;
    1816           0 :     SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
    1817           0 :     linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
    1818           0 :     sal_uInt16 i, j = 0;
    1819           0 :     if( pWrong )
    1820             :     {
    1821           0 :         for( i = 0; i < rResult.aErrors.getLength(); ++i )
    1822             :         {
    1823           0 :             const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
    1824           0 :             xub_StrLen nStart = (xub_StrLen)rConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos;
    1825           0 :             xub_StrLen nEnd = (xub_StrLen)rConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos;
    1826           0 :             if( i != j )
    1827           0 :                 pArray[j] = pArray[i];
    1828           0 :             if( pWrong->LookForEntry( nStart, nEnd ) )
    1829           0 :                 ++j;
    1830             :         }
    1831             :     }
    1832           0 :     if( rResult.aErrors.getLength() > j )
    1833           0 :         rResult.aErrors.realloc( j );
    1834             : }
    1835             : 
    1836           0 : uno::Any SwDoc::Spell( SwPaM& rPaM,
    1837             :                     uno::Reference< XSpellChecker1 >  &xSpeller,
    1838             :                     sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
    1839             :                     bool bGrammarCheck,
    1840             :                     SwConversionArgs *pConvArgs  ) const
    1841             : {
    1842           0 :     SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
    1843           0 :     uno::Reference< beans::XPropertySet >  xProp( ::GetLinguPropertySet() );
    1844             : 
    1845           0 :     SwSpellArgs      *pSpellArgs = 0;
    1846           0 :     if (pConvArgs)
    1847             :     {
    1848           0 :         pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
    1849           0 :         pConvArgs->SetEnd(  pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
    1850             :     }
    1851             :     else
    1852             :         pSpellArgs = new SwSpellArgs( xSpeller,
    1853           0 :                             pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
    1854           0 :                             pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
    1855           0 :                             bGrammarCheck );
    1856             : 
    1857           0 :     sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
    1858           0 :     sal_uLong nEndNd = pEndPos->nNode.GetIndex();
    1859             : 
    1860           0 :     uno::Any aRet;
    1861           0 :     if( nCurrNd <= nEndNd )
    1862             :     {
    1863             :         SwCntntFrm* pCntFrm;
    1864           0 :         bool bGoOn = true;
    1865           0 :         while( bGoOn )
    1866             :         {
    1867           0 :             SwNode* pNd = GetNodes()[ nCurrNd ];
    1868           0 :             switch( pNd->GetNodeType() )
    1869             :             {
    1870             :             case ND_TEXTNODE:
    1871           0 :                 if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( GetCurrentLayout() )) )
    1872             :                 {
    1873             :                     // skip protected and hidden Cells and Flys
    1874           0 :                     if( pCntFrm->IsProtected() )
    1875             :                     {
    1876           0 :                         nCurrNd = pNd->EndOfSectionIndex();
    1877             :                     }
    1878           0 :                     else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
    1879             :                     {
    1880           0 :                         if( pPageCnt && *pPageCnt && pPageSt )
    1881             :                         {
    1882           0 :                             sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
    1883           0 :                             if( !*pPageSt )
    1884             :                             {
    1885           0 :                                 *pPageSt = nPageNr;
    1886           0 :                                 if( *pPageCnt < *pPageSt )
    1887           0 :                                     *pPageCnt = *pPageSt;
    1888             :                             }
    1889             :                             long nStat;
    1890           0 :                             if( nPageNr >= *pPageSt )
    1891           0 :                                 nStat = nPageNr - *pPageSt + 1;
    1892             :                             else
    1893           0 :                                 nStat = nPageNr + *pPageCnt - *pPageSt + 1;
    1894           0 :                             ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
    1895             :                         }
    1896             :                         //Spell() changes the pSpellArgs in case an error is found
    1897           0 :                         xub_StrLen nBeginGrammarCheck = 0;
    1898           0 :                         xub_StrLen nEndGrammarCheck = 0;
    1899           0 :                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
    1900             :                         {
    1901           0 :                             nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ?  pSpellArgs->pStartIdx->GetIndex() : 0;
    1902             :                             // if grammar checking starts inside of a sentence the start position has to be adjusted
    1903           0 :                             if( nBeginGrammarCheck )
    1904             :                             {
    1905           0 :                                 SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
    1906           0 :                                 SwPosition aStart( *pNd, aStartIndex );
    1907           0 :                                 SwCursor aCrsr(aStart, 0, false);
    1908           0 :                                 SwPosition aOrigPos = *aCrsr.GetPoint();
    1909           0 :                                 aCrsr.GoSentence( SwCursor::START_SENT );
    1910           0 :                                 if( aOrigPos != *aCrsr.GetPoint() )
    1911             :                                 {
    1912           0 :                                     nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
    1913           0 :                                 }
    1914             :                             }
    1915           0 :                             nEndGrammarCheck = pSpellArgs->pEndNode == pNd ? pSpellArgs->pEndIdx->GetIndex() : ((SwTxtNode*)pNd)->GetTxt().Len();
    1916             :                         }
    1917             : 
    1918           0 :                         xub_StrLen nSpellErrorPosition = ((SwTxtNode*)pNd)->GetTxt().Len();
    1919           0 :                         if( (!pConvArgs &&
    1920           0 :                                 ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
    1921             :                             ( pConvArgs &&
    1922           0 :                                 ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
    1923             :                         {
    1924             :                             // Cancel and remember position
    1925           0 :                             pSttPos->nNode = nCurrNd;
    1926           0 :                             pEndPos->nNode = nCurrNd;
    1927           0 :                             nCurrNd = nEndNd;
    1928           0 :                             if( pSpellArgs )
    1929           0 :                                 nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
    1930           0 :                                             pSpellArgs->pEndIdx->GetIndex() :
    1931           0 :                                             pSpellArgs->pStartIdx->GetIndex();
    1932             :                         }
    1933             : 
    1934             : 
    1935           0 :                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
    1936             :                         {
    1937           0 :                             uno::Reference< linguistic2::XProofreadingIterator >  xGCIterator( GetGCIterator() );
    1938           0 :                             if (xGCIterator.is())
    1939             :                             {
    1940           0 :                                 uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
    1941             :                                 // Expand the string:
    1942           0 :                                 const ModelToViewHelper aConversionMap(*(SwTxtNode*)pNd);
    1943           0 :                                 rtl::OUString aExpandText = aConversionMap.getViewText();
    1944             : 
    1945             :                                 // get XFlatParagraph to use...
    1946           0 :                                 uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, aConversionMap );
    1947             : 
    1948             :                                 // get error position of cursor in XFlatParagraph
    1949           0 :                                 linguistic2::ProofreadingResult aResult;
    1950             :                                 sal_Int32 nGrammarErrors;
    1951           0 :                                 do
    1952             :                                 {
    1953           0 :                                     aConversionMap.ConvertToViewPosition( nBeginGrammarCheck );
    1954           0 :                                     aResult = xGCIterator->checkSentenceAtPosition(
    1955           0 :                                             xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
    1956             : 
    1957           0 :                                     lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, nBeginGrammarCheck, aConversionMap );
    1958             : 
    1959             :                                     // get suggestions to use for the specific error position
    1960           0 :                                     nGrammarErrors = aResult.aErrors.getLength();
    1961             :                                     // if grammar checking doesn't have any progress then quit
    1962           0 :                                     if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
    1963           0 :                                         break;
    1964             :                                     // prepare next iteration
    1965           0 :                                     nBeginGrammarCheck = (xub_StrLen)aResult.nStartOfNextSentencePosition;
    1966             :                                 }
    1967             :                                 while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
    1968             : 
    1969           0 :                                 if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
    1970             :                                 {
    1971           0 :                                     aRet <<= aResult;
    1972             :                                     //put the cursor to the current error
    1973           0 :                                     const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
    1974           0 :                                     nCurrNd = pNd->GetIndex();
    1975           0 :                                     pSttPos->nNode = nCurrNd;
    1976           0 :                                     pEndPos->nNode = nCurrNd;
    1977           0 :                                     pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
    1978           0 :                                     pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
    1979           0 :                                     pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)aConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos );
    1980           0 :                                     pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)aConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos );
    1981           0 :                                     nCurrNd = nEndNd;
    1982           0 :                                 }
    1983           0 :                             }
    1984             :                         }
    1985             :                     }
    1986             :                 }
    1987           0 :                 break;
    1988             :             case ND_SECTIONNODE:
    1989           0 :                 if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
    1990           0 :                     ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
    1991           0 :                     nCurrNd = pNd->EndOfSectionIndex();
    1992           0 :                 break;
    1993             :             case ND_ENDNODE:
    1994             :                 {
    1995           0 :                     break;
    1996             :                 }
    1997             :             }
    1998             : 
    1999           0 :             bGoOn = nCurrNd < nEndNd;
    2000           0 :             ++nCurrNd;
    2001             :         }
    2002             :     }
    2003             : 
    2004           0 :     if( !aRet.hasValue() )
    2005             :     {
    2006           0 :         if (pConvArgs)
    2007           0 :             aRet <<= pConvArgs->aConvText;
    2008             :         else
    2009           0 :             aRet <<= pSpellArgs->xSpellAlt;
    2010             :     }
    2011           0 :     delete pSpellArgs;
    2012             : 
    2013           0 :     return aRet;
    2014             : }
    2015             : 
    2016           0 : class SwHyphArgs : public SwInterHyphInfo
    2017             : {
    2018             :     const SwNode *pStart;
    2019             :     const SwNode *pEnd;
    2020             :           SwNode *pNode;
    2021             :     sal_uInt16 *pPageCnt;
    2022             :     sal_uInt16 *pPageSt;
    2023             : 
    2024             :     sal_uInt32 nNode;
    2025             :     xub_StrLen nPamStart;
    2026             :     xub_StrLen nPamLen;
    2027             : 
    2028             : public:
    2029             :          SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
    2030             :                          sal_uInt16* pPageCount, sal_uInt16* pPageStart );
    2031             :     void SetPam( SwPaM *pPam ) const;
    2032           0 :     inline void SetNode( SwNode *pNew ) { pNode = pNew; }
    2033             :     inline const SwNode *GetNode() const { return pNode; }
    2034             :     inline void SetRange( const SwNode *pNew );
    2035           0 :     inline void NextNode() { ++nNode; }
    2036           0 :     inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
    2037           0 :     inline sal_uInt16 *GetPageSt() { return pPageSt; }
    2038             : };
    2039             : 
    2040           0 : SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
    2041             :                          sal_uInt16* pPageCount, sal_uInt16* pPageStart )
    2042             :      : SwInterHyphInfo( rCrsrPos ), pNode(0),
    2043           0 :      pPageCnt( pPageCount ), pPageSt( pPageStart )
    2044             : {
    2045             :     // The following constraints have to be met:
    2046             :     // 1) there is at least one Selection
    2047             :     // 2) SPoint() == Start()
    2048             :     OSL_ENSURE( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
    2049             :     OSL_ENSURE( *pPam->GetPoint() <= *pPam->GetMark(),
    2050             :             "SwDoc::Hyphenate: New York, New York");
    2051             : 
    2052           0 :     const SwPosition *pPoint = pPam->GetPoint();
    2053           0 :     nNode = pPoint->nNode.GetIndex();
    2054             : 
    2055             :     // Set start
    2056           0 :     pStart = pPoint->nNode.GetNode().GetTxtNode();
    2057           0 :     nPamStart = pPoint->nContent.GetIndex();
    2058             : 
    2059             :     // Set End and Length
    2060           0 :     const SwPosition *pMark = pPam->GetMark();
    2061           0 :     pEnd = pMark->nNode.GetNode().GetTxtNode();
    2062           0 :     nPamLen = pMark->nContent.GetIndex();
    2063           0 :     if( pPoint->nNode == pMark->nNode )
    2064           0 :         nPamLen = nPamLen - pPoint->nContent.GetIndex();
    2065           0 : }
    2066             : 
    2067           0 : inline void SwHyphArgs::SetRange( const SwNode *pNew )
    2068             : {
    2069           0 :     nStart = pStart == pNew ? nPamStart : 0;
    2070           0 :     nLen   = pEnd   == pNew ? nPamLen : STRING_NOTFOUND;
    2071           0 : }
    2072             : 
    2073           0 : void SwHyphArgs::SetPam( SwPaM *pPam ) const
    2074             : {
    2075           0 :     if( !pNode )
    2076           0 :         *pPam->GetPoint() = *pPam->GetMark();
    2077             :     else
    2078             :     {
    2079           0 :         pPam->GetPoint()->nNode = nNode;
    2080           0 :         pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
    2081           0 :         pPam->GetMark()->nNode = nNode;
    2082           0 :         pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
    2083           0 :                                           nWordStart + nWordLen );
    2084             :         OSL_ENSURE( nNode == pNode->GetIndex(),
    2085             :                 "SwHyphArgs::SetPam: Pam disaster" );
    2086             :     }
    2087           0 : }
    2088             : 
    2089             : // Returns sal_True if we can proceed.
    2090           0 : static bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
    2091             : {
    2092             :     // Hyphenate returns true if there is a hyphenation point and sets pPam
    2093           0 :     SwTxtNode *pNode = rpNd->GetTxtNode();
    2094           0 :     SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
    2095           0 :     if( pNode )
    2096             :     {
    2097           0 :         SwCntntFrm* pCntFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout() );
    2098           0 :         if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
    2099             :         {
    2100           0 :             sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
    2101           0 :             sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
    2102           0 :             if( pPageCnt && *pPageCnt && pPageSt )
    2103             :             {
    2104           0 :                 sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
    2105           0 :                 if( !*pPageSt )
    2106             :                 {
    2107           0 :                     *pPageSt = nPageNr;
    2108           0 :                     if( *pPageCnt < *pPageSt )
    2109           0 :                         *pPageCnt = *pPageSt;
    2110             :                 }
    2111             :                 long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
    2112           0 :                                          : nPageNr + *pPageCnt - *pPageSt + 1;
    2113           0 :                 ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
    2114             :             }
    2115           0 :             pHyphArgs->SetRange( rpNd );
    2116           0 :             if( pNode->Hyphenate( *pHyphArgs ) )
    2117             :             {
    2118           0 :                 pHyphArgs->SetNode( rpNd );
    2119           0 :                 return false;
    2120             :             }
    2121             :         }
    2122             :     }
    2123           0 :     pHyphArgs->NextNode();
    2124           0 :     return true;
    2125             : }
    2126             : 
    2127           0 : uno::Reference< XHyphenatedWord >  SwDoc::Hyphenate(
    2128             :                             SwPaM *pPam, const Point &rCrsrPos,
    2129             :                              sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
    2130             : {
    2131             :     OSL_ENSURE(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
    2132             : 
    2133           0 :     if( *pPam->GetPoint() > *pPam->GetMark() )
    2134           0 :         pPam->Exchange();
    2135             : 
    2136           0 :     SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
    2137           0 :     SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
    2138           0 :     GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
    2139           0 :                     lcl_HyphenateNode, &aHyphArg );
    2140           0 :     aHyphArg.SetPam( pPam );
    2141           0 :     return aHyphArg.GetHyphWord();  // will be set by lcl_HyphenateNode
    2142             : }
    2143             : 
    2144           0 : static bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, bool bRegExpRplc )
    2145             : {
    2146           0 :     bool bRet = false;
    2147           0 :     if( bRegExpRplc )
    2148             :     {
    2149           0 :         xub_StrLen nPos = 0;
    2150           0 :         rtl::OUString sPara("\\n");
    2151           0 :         while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
    2152             :         {
    2153             :             // Has this been escaped?
    2154           0 :             if( nPos && '\\' == rStr.GetChar( nPos-1 ))
    2155             :             {
    2156           0 :                 if( ++nPos >= rStr.Len() )
    2157           0 :                     break;
    2158             :             }
    2159             :             else
    2160             :             {
    2161           0 :                 rRet = rStr.Copy( 0, nPos );
    2162           0 :                 rStr.Erase( 0, nPos + sPara.getLength() );
    2163           0 :                 bRet = true;
    2164           0 :                 break;
    2165             :             }
    2166           0 :         }
    2167             :     }
    2168           0 :     if( !bRet )
    2169             :     {
    2170           0 :         rRet = rStr;
    2171           0 :         rStr.Erase();
    2172             :     }
    2173           0 :     return bRet;
    2174             : }
    2175             : 
    2176           0 : bool SwDoc::ReplaceRange( SwPaM& rPam, const String& rStr,
    2177             :         const bool bRegExReplace )
    2178             : {
    2179             :     // unfortunately replace works slightly differently from delete,
    2180             :     // so we cannot use lcl_DoWithBreaks here...
    2181             : 
    2182           0 :     ::std::vector<xub_StrLen> Breaks;
    2183             : 
    2184           0 :     SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
    2185           0 :     aPam.Normalize(sal_False);
    2186           0 :     if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
    2187             :     {
    2188           0 :         aPam.Move(fnMoveBackward);
    2189             :     }
    2190             :    OSL_ENSURE((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
    2191             : 
    2192           0 :     lcl_CalcBreaks(Breaks, aPam);
    2193             : 
    2194           0 :     while (!Breaks.empty() // skip over prefix of dummy chars
    2195           0 :             && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
    2196             :     {
    2197             :         // skip!
    2198           0 :         ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
    2199           0 :         Breaks.erase(Breaks.begin());
    2200             :     }
    2201           0 :     *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
    2202             : 
    2203           0 :     if (!Breaks.size())
    2204             :     {
    2205             :         // park aPam somewhere so it does not point to node that is deleted
    2206           0 :         aPam.DeleteMark();
    2207           0 :         *aPam.GetPoint() = SwPosition(GetNodes().GetEndOfContent());
    2208           0 :         return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
    2209             :     }
    2210             : 
    2211             :     // Deletion must be split into several parts if the text node
    2212             :     // contains a text attribute with end and with dummy character
    2213             :     // and the selection does not contain the text attribute completely,
    2214             :     // but overlaps its start (left), where the dummy character is.
    2215             : 
    2216           0 :     bool bRet( true );
    2217             :     // iterate from end to start, to avoid invalidating the offsets!
    2218           0 :     ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
    2219             :     OSL_ENSURE(aPam.GetPoint() == aPam.End(), "wrong!");
    2220           0 :     SwPosition & rEnd( *aPam.End() );
    2221           0 :     SwPosition & rStart( *aPam.Start() );
    2222             : 
    2223             :     // set end of temp pam to original end (undo Move backward above)
    2224           0 :     rEnd = *rPam.End();
    2225             :     // after first deletion, rEnd will point into the original text node again!
    2226             : 
    2227           0 :     while (iter != Breaks.rend())
    2228             :     {
    2229           0 :         rStart.nContent = *iter + 1;
    2230           0 :         if (rEnd.nContent != rStart.nContent) // check if part is empty
    2231             :         {
    2232           0 :             bRet &= (IsRedlineOn())
    2233             :                 ? DeleteAndJoinWithRedlineImpl(aPam)
    2234           0 :                 : DeleteAndJoinImpl(aPam, false);
    2235             :         }
    2236           0 :         rEnd.nContent = *iter;
    2237           0 :         ++iter;
    2238             :     }
    2239             : 
    2240           0 :     rStart = *rPam.Start(); // set to original start
    2241             :     OSL_ENSURE(rEnd.nContent > rStart.nContent, "replace part empty!");
    2242           0 :     if (rEnd.nContent > rStart.nContent) // check if part is empty
    2243             :     {
    2244           0 :         bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
    2245             :     }
    2246             : 
    2247           0 :     rPam = aPam; // update original pam (is this required?)
    2248             : 
    2249           0 :     return bRet;
    2250             : }
    2251             : 
    2252             : // It's possible to call Replace with a PaM that spans 2 paragraphs:
    2253             : // search with regex for "$", then replace _all_
    2254           0 : bool SwDoc::ReplaceRangeImpl( SwPaM& rPam, const String& rStr,
    2255             :         const bool bRegExReplace )
    2256             : {
    2257           0 :     if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
    2258           0 :         return false;
    2259             : 
    2260             :     sal_Bool bJoinTxt, bJoinPrev;
    2261           0 :     sw_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
    2262             : 
    2263             :     {
    2264             :         // Create a copy of the Cursor in order to move all Pams from
    2265             :         // the other views out of the deletion range.
    2266             :         // Except for itself!
    2267           0 :         SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
    2268           0 :         ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
    2269             : 
    2270           0 :         SwPosition *pStt = (SwPosition*)aDelPam.Start(),
    2271           0 :                    *pEnd = (SwPosition*)aDelPam.End();
    2272             :         OSL_ENSURE( pStt->nNode == pEnd->nNode ||
    2273             :                 ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
    2274             :                     !pEnd->nContent.GetIndex() ),
    2275             :                 "invalid range: Point and Mark on different nodes" );
    2276           0 :         sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
    2277             : 
    2278             :         // Own Undo?
    2279           0 :         String sRepl( rStr );
    2280           0 :         SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
    2281           0 :         xub_StrLen nStt = pStt->nContent.GetIndex(),
    2282           0 :                 nEnd = bOneNode ? pEnd->nContent.GetIndex()
    2283           0 :                                 : pTxtNd->GetTxt().Len();
    2284             : 
    2285           0 :         SwDataChanged aTmp( aDelPam );
    2286             : 
    2287           0 :         if( IsRedlineOn() )
    2288             :         {
    2289           0 :             RedlineMode_t eOld = GetRedlineMode();
    2290           0 :             checkRedlining(eOld);
    2291           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    2292             :             {
    2293           0 :                 GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
    2294             : 
    2295             :                 // If any Redline will change (split!) the node
    2296           0 :                 const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
    2297             : 
    2298             :                 //JP 06.01.98: MUSS noch optimiert werden!!!
    2299             :                 SetRedlineMode(
    2300           0 :                     (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
    2301             : 
    2302           0 :                 *aDelPam.GetPoint() = pBkmk->GetMarkPos();
    2303           0 :                 if(pBkmk->IsExpanded())
    2304           0 :                     *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
    2305           0 :                 getIDocumentMarkAccess()->deleteMark(pBkmk);
    2306           0 :                 pStt = aDelPam.Start();
    2307           0 :                 pTxtNd = pStt->nNode.GetNode().GetTxtNode();
    2308           0 :                 nStt = pStt->nContent.GetIndex();
    2309             :             }
    2310             : 
    2311           0 :             if( sRepl.Len() )
    2312             :             {
    2313             :                 // Apply the first character's attributes to the ReplaceText
    2314           0 :                 SfxItemSet aSet( GetAttrPool(),
    2315             :                             RES_CHRATR_BEGIN,     RES_TXTATR_WITHEND_END - 1,
    2316             :                             RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
    2317           0 :                             0 );
    2318           0 :                 pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
    2319             : 
    2320           0 :                 aSet.ClearItem( RES_TXTATR_REFMARK );
    2321           0 :                 aSet.ClearItem( RES_TXTATR_TOXMARK );
    2322           0 :                 aSet.ClearItem( RES_TXTATR_CJK_RUBY );
    2323           0 :                 aSet.ClearItem( RES_TXTATR_INETFMT );
    2324           0 :                 aSet.ClearItem( RES_TXTATR_META );
    2325           0 :                 aSet.ClearItem( RES_TXTATR_METAFIELD );
    2326             : 
    2327           0 :                 if( aDelPam.GetPoint() != aDelPam.End() )
    2328           0 :                     aDelPam.Exchange();
    2329             : 
    2330             :                 // Remember the End
    2331           0 :                 SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
    2332           0 :                 xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
    2333             : 
    2334           0 :                 bool bFirst = true;
    2335           0 :                 String sIns;
    2336           0 :                 while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
    2337             :                 {
    2338           0 :                     InsertString( aDelPam, sIns );
    2339           0 :                     if( bFirst )
    2340             :                     {
    2341           0 :                         SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
    2342           0 :                         xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
    2343             : 
    2344           0 :                         SplitNode( *aDelPam.GetPoint(), false );
    2345             : 
    2346           0 :                         ++aMkNd;
    2347           0 :                         aDelPam.GetMark()->nNode = aMkNd;
    2348           0 :                         aDelPam.GetMark()->nContent.Assign(
    2349           0 :                                     aMkNd.GetNode().GetCntntNode(), nMkCnt );
    2350           0 :                         bFirst = false;
    2351             :                     }
    2352             :                     else
    2353           0 :                         SplitNode( *aDelPam.GetPoint(), false );
    2354             :                 }
    2355           0 :                 if( sIns.Len() )
    2356             :                 {
    2357           0 :                     InsertString( aDelPam, sIns );
    2358             :                 }
    2359             : 
    2360           0 :                 SwPaM aTmpRange( *aDelPam.GetPoint() );
    2361           0 :                 aTmpRange.SetMark();
    2362             : 
    2363           0 :                 ++aPtNd;
    2364           0 :                 aDelPam.GetPoint()->nNode = aPtNd;
    2365           0 :                 aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
    2366           0 :                                                     nPtCnt);
    2367           0 :                 *aTmpRange.GetMark() = *aDelPam.GetPoint();
    2368             : 
    2369           0 :                 RstTxtAttrs( aTmpRange );
    2370           0 :                 InsertItemSet( aTmpRange, aSet, 0 );
    2371             :             }
    2372             : 
    2373           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    2374             :             {
    2375             :                 SwUndo *const pUndoRD =
    2376           0 :                     new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
    2377           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndoRD);
    2378             :             }
    2379           0 :             AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
    2380             : 
    2381           0 :             *rPam.GetMark() = *aDelPam.GetMark();
    2382           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    2383             :             {
    2384           0 :                 *aDelPam.GetPoint() = *rPam.GetPoint();
    2385           0 :                 GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
    2386             : 
    2387             :                 // If any Redline will change (split!) the node
    2388           0 :                 const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
    2389             : 
    2390           0 :                 SwIndex& rIdx = aDelPam.GetPoint()->nContent;
    2391           0 :                 rIdx.Assign( 0, 0 );
    2392           0 :                 aDelPam.GetMark()->nContent = rIdx;
    2393           0 :                 rPam.GetPoint()->nNode = 0;
    2394           0 :                 rPam.GetPoint()->nContent = rIdx;
    2395           0 :                 *rPam.GetMark() = *rPam.GetPoint();
    2396             : //JP 06.01.98: MUSS noch optimiert werden!!!
    2397           0 : SetRedlineMode( eOld );
    2398             : 
    2399           0 :                 *rPam.GetPoint() = pBkmk->GetMarkPos();
    2400           0 :                 if(pBkmk->IsExpanded())
    2401           0 :                     *rPam.GetMark() = pBkmk->GetOtherMarkPos();
    2402           0 :                 getIDocumentMarkAccess()->deleteMark(pBkmk);
    2403             :             }
    2404           0 :             bJoinTxt = sal_False;
    2405             :         }
    2406             :         else
    2407             :         {
    2408           0 :             if( !IsIgnoreRedline() && GetRedlineTbl().size() )
    2409           0 :                 DeleteRedline( aDelPam, true, USHRT_MAX );
    2410             : 
    2411           0 :             SwUndoReplace* pUndoRpl = 0;
    2412           0 :             bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
    2413           0 :             if (bDoesUndo)
    2414             :             {
    2415           0 :                 pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
    2416           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
    2417             :             }
    2418           0 :             ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
    2419             : 
    2420           0 :             if( aDelPam.GetPoint() != pStt )
    2421           0 :                 aDelPam.Exchange();
    2422             : 
    2423           0 :             SwNodeIndex aPtNd( pStt->nNode, -1 );
    2424           0 :             xub_StrLen nPtCnt = pStt->nContent.GetIndex();
    2425             : 
    2426             :             // Set the values again, if Frames or footnotes on the Text have been removed.
    2427           0 :             nStt = nPtCnt;
    2428           0 :             nEnd = bOneNode ? pEnd->nContent.GetIndex()
    2429           0 :                             : pTxtNd->GetTxt().Len();
    2430             : 
    2431           0 :             bool bFirst = true;
    2432           0 :             String sIns;
    2433           0 :             while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
    2434             :             {
    2435           0 :                 if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
    2436             :                 {
    2437           0 :                     InsertString( aDelPam, sIns );
    2438             :                 }
    2439           0 :                 else if( nStt < nEnd || sIns.Len() )
    2440             :                 {
    2441           0 :                     pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
    2442             :                 }
    2443           0 :                 SplitNode( *pStt, false);
    2444           0 :                 bFirst = false;
    2445             :             }
    2446             : 
    2447           0 :             if( bFirst || sIns.Len() )
    2448             :             {
    2449           0 :                 if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
    2450             :                 {
    2451           0 :                     InsertString( aDelPam, sIns );
    2452             :                 }
    2453           0 :                 else if( nStt < nEnd || sIns.Len() )
    2454             :                 {
    2455           0 :                     pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
    2456             :                 }
    2457             :             }
    2458             : 
    2459           0 :             *rPam.GetMark() = *aDelPam.GetMark();
    2460             : 
    2461           0 :             ++aPtNd;
    2462           0 :             rPam.GetMark()->nNode = aPtNd;
    2463           0 :             rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
    2464           0 :                                                 nPtCnt );
    2465             : 
    2466           0 :             if (bJoinTxt && !bJoinPrev)
    2467             :             {
    2468           0 :                 rPam.Move(fnMoveBackward);
    2469             :             }
    2470             : 
    2471           0 :             if( pUndoRpl )
    2472             :             {
    2473           0 :                 pUndoRpl->SetEnd(rPam);
    2474           0 :             }
    2475           0 :         }
    2476             :     }
    2477             : 
    2478           0 :     if( bJoinTxt )
    2479           0 :         sw_JoinText( rPam, bJoinPrev );
    2480             : 
    2481           0 :     SetModified();
    2482           0 :     return true;
    2483             : }
    2484             : 
    2485             : // Save the current values to add them as automatic entries to to AutoCorrect.
    2486           0 : void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
    2487             : {
    2488           0 :     if( pNew != pACEWord )
    2489           0 :         delete pACEWord;
    2490           0 :     pACEWord = pNew;
    2491           0 : }
    2492             : 
    2493         628 : bool SwDoc::DelFullPara( SwPaM& rPam )
    2494             : {
    2495         628 :     const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
    2496         628 :     const SwNode* pNd = &rStt.nNode.GetNode();
    2497         628 :     sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
    2498         628 :                         pNd->StartOfSectionIndex();
    2499         628 :     sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
    2500             : 
    2501         984 :     if ( nSectDiff-2 <= nNodeDiff || IsRedlineOn() ||
    2502             :          /* #i9185# Prevent getting the node after the end node (see below) */
    2503         356 :         rEnd.nNode.GetIndex() + 1 == GetNodes().Count() )
    2504             :     {
    2505         450 :         return sal_False;
    2506             :     }
    2507             : 
    2508             :     // Move hard page brakes to the following Node.
    2509         178 :     sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
    2510             : 
    2511             :     /* #i9185# This whould lead to a segmentation fault if not caught above. */
    2512         178 :     sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
    2513         178 :     SwTableNode *const pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
    2514             : 
    2515         178 :     if( pTblNd && pNd->IsCntntNode() )
    2516             :     {
    2517           1 :         SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
    2518             : 
    2519             :         {
    2520             :             const SfxPoolItem *pItem;
    2521           1 :             const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
    2522           1 :             if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
    2523           0 :                 sal_False, &pItem ) )
    2524             :             {
    2525           0 :                 pTableFmt->SetFmtAttr( *pItem );
    2526           0 :                 bSavePageDesc = sal_True;
    2527             :             }
    2528             : 
    2529           1 :             if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
    2530           0 :                 sal_False, &pItem ) )
    2531             :             {
    2532           0 :                 pTableFmt->SetFmtAttr( *pItem );
    2533           0 :                 bSavePageBreak = sal_True;
    2534             :             }
    2535             :         }
    2536             :     }
    2537             : 
    2538         178 :     bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
    2539         178 :     if( bDoesUndo )
    2540             :     {
    2541           0 :         if( !rPam.HasMark() )
    2542           0 :             rPam.SetMark();
    2543           0 :         else if( rPam.GetPoint() == &rStt )
    2544           0 :             rPam.Exchange();
    2545           0 :         rPam.GetPoint()->nNode++;
    2546             : 
    2547           0 :         SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
    2548           0 :         rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
    2549           0 :         bool bGoNext = (0 == pTmpNode);
    2550           0 :         pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
    2551           0 :         rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
    2552             : 
    2553           0 :         GetIDocumentUndoRedo().ClearRedo();
    2554             : 
    2555           0 :         SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
    2556             :         {
    2557           0 :             SwPosition aTmpPos( *aDelPam.GetPoint() );
    2558           0 :             if( bGoNext )
    2559             :             {
    2560           0 :                 pTmpNode = GetNodes().GoNext( &aTmpPos.nNode );
    2561           0 :                 aTmpPos.nContent.Assign( pTmpNode, 0 );
    2562             :             }
    2563           0 :             ::PaMCorrAbs( aDelPam, aTmpPos );
    2564             :         }
    2565             : 
    2566           0 :         SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, sal_True );
    2567             : 
    2568           0 :         *rPam.GetPoint() = *aDelPam.GetPoint();
    2569           0 :         pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
    2570           0 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
    2571             :     }
    2572             :     else
    2573             :     {
    2574         178 :         SwNodeRange aRg( rStt.nNode, rEnd.nNode );
    2575         178 :         if( rPam.GetPoint() != &rEnd )
    2576           0 :             rPam.Exchange();
    2577             : 
    2578             :         // Try to move past the End
    2579         178 :         if( !rPam.Move( fnMoveForward, fnGoNode ) )
    2580             :         {
    2581             :             // Fair enough, at the Beginning then
    2582          48 :             rPam.Exchange();
    2583          48 :             if( !rPam.Move( fnMoveBackward, fnGoNode ))
    2584             :             {
    2585             :                 OSL_FAIL( "no more Nodes" );
    2586           0 :                 return sal_False;
    2587             :             }
    2588             :         }
    2589             :         // move bookmarks, redlines etc.
    2590         178 :         if (aRg.aStart == aRg.aEnd) // only first CorrAbs variant handles this
    2591             :         {
    2592         178 :             CorrAbs( aRg.aStart, *rPam.GetPoint(), 0, sal_True );
    2593             :         }
    2594             :         else
    2595             :         {
    2596           0 :             CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
    2597             :         }
    2598             : 
    2599             :             // What's with Flys?
    2600             :         {
    2601             :             // If there are FlyFrames left, delete these too
    2602         254 :             for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->size(); ++n )
    2603             :             {
    2604          76 :                 SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
    2605          76 :                 const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
    2606          76 :                 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
    2607         296 :                 if (pAPos &&
    2608          76 :                     ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
    2609          21 :                      (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
    2610         123 :                     aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
    2611             :                 {
    2612           0 :                     DelLayoutFmt( pFly );
    2613           0 :                     --n;
    2614             :                 }
    2615             :             }
    2616             :         }
    2617             : 
    2618         178 :         SwCntntNode *pTmpNode = rPam.GetBound( sal_True ).nNode.GetNode().GetCntntNode();
    2619         178 :         rPam.GetBound( sal_True ).nContent.Assign( pTmpNode, 0 );
    2620         178 :         pTmpNode = rPam.GetBound( sal_False ).nNode.GetNode().GetCntntNode();
    2621         178 :         rPam.GetBound( sal_False ).nContent.Assign( pTmpNode, 0 );
    2622         178 :         GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
    2623             :     }
    2624         178 :     rPam.DeleteMark();
    2625         178 :     SetModified();
    2626             : 
    2627         178 :     return sal_True;
    2628             : }
    2629             : 
    2630           0 : void SwDoc::TransliterateText(
    2631             :     const SwPaM& rPaM,
    2632             :     utl::TransliterationWrapper& rTrans )
    2633             : {
    2634           0 :     SwUndoTransliterate *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
    2635           0 :         ?   new SwUndoTransliterate( rPaM, rTrans )
    2636           0 :         :   0;
    2637             : 
    2638           0 :     const SwPosition* pStt = rPaM.Start(),
    2639           0 :                        * pEnd = rPaM.End();
    2640           0 :     sal_uLong nSttNd = pStt->nNode.GetIndex(),
    2641           0 :           nEndNd = pEnd->nNode.GetIndex();
    2642           0 :     xub_StrLen nSttCnt = pStt->nContent.GetIndex(),
    2643           0 :                nEndCnt = pEnd->nContent.GetIndex();
    2644             : 
    2645           0 :     SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
    2646           0 :     if( pStt == pEnd && pTNd )  // no selection?
    2647             :     {
    2648             :         // set current word as 'area of effect'
    2649             : 
    2650           0 :         Boundary aBndry;
    2651           0 :         if( pBreakIt->GetBreakIter().is() )
    2652           0 :             aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
    2653           0 :                         pTNd->GetTxt(), nSttCnt,
    2654           0 :                         pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
    2655             :                         WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
    2656           0 :                         sal_True );
    2657             : 
    2658           0 :         if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
    2659             :         {
    2660           0 :             nSttCnt = (xub_StrLen)aBndry.startPos;
    2661           0 :             nEndCnt = (xub_StrLen)aBndry.endPos;
    2662             :         }
    2663             :     }
    2664             : 
    2665           0 :     if( nSttNd != nEndNd )  // is more than one text node involved?
    2666             :     {
    2667             :         // iterate over all effected text nodes, the first and the last one
    2668             :         // may be incomplete because the selection starts and/or ends there
    2669             : 
    2670           0 :         SwNodeIndex aIdx( pStt->nNode );
    2671           0 :         if( nSttCnt )
    2672             :         {
    2673           0 :             ++aIdx;
    2674           0 :             if( pTNd )
    2675           0 :                 pTNd->TransliterateText( rTrans, nSttCnt, pTNd->GetTxt().Len(), pUndo );
    2676             :         }
    2677             : 
    2678           0 :         for( ; aIdx.GetIndex() < nEndNd; ++aIdx )
    2679             :         {
    2680           0 :             if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
    2681           0 :                 pTNd->TransliterateText( rTrans, 0, pTNd->GetTxt().Len(), pUndo );
    2682             :         }
    2683             : 
    2684           0 :         if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
    2685           0 :             pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
    2686             :     }
    2687           0 :     else if( pTNd && nSttCnt < nEndCnt )
    2688           0 :         pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
    2689             : 
    2690           0 :     if( pUndo )
    2691             :     {
    2692           0 :         if( pUndo->HasData() )
    2693             :         {
    2694           0 :             GetIDocumentUndoRedo().AppendUndo(pUndo);
    2695             :         }
    2696             :         else
    2697           0 :             delete pUndo;
    2698             :     }
    2699           0 :     SetModified();
    2700           0 : }
    2701             : 
    2702             : #define MAX_REDLINE_COUNT   250
    2703             : 
    2704         218 : void SwDoc::checkRedlining(RedlineMode_t& _rReadlineMode)
    2705             : {
    2706         218 :     const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
    2707         218 :     SwEditShell* pEditShell = GetEditShell();
    2708         218 :     Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
    2709         218 :     if ( pParent && !mbReadlineChecked && rRedlineTbl.size() > MAX_REDLINE_COUNT
    2710           0 :         && !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
    2711             :     {
    2712           0 :         WarningBox aWarning( pParent,SW_RES(MSG_DISABLE_READLINE_QUESTION));
    2713           0 :         sal_uInt16 nResult = aWarning.Execute();
    2714           0 :         mbReadlineChecked = sal_True;
    2715           0 :         if ( nResult == RET_YES )
    2716             :         {
    2717           0 :             sal_Int32 nMode = (sal_Int32)_rReadlineMode;
    2718           0 :             nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
    2719           0 :             _rReadlineMode = (RedlineMode_t)nMode;
    2720           0 :         }
    2721             :     }
    2722         218 : }
    2723             : 
    2724           0 : void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
    2725             : {
    2726             :     // This is a modified version of SwDoc::TransliterateText
    2727           0 :     const SwPosition* pStt = rPaM.Start();
    2728           0 :     const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
    2729           0 :                                                      : rPaM.GetPoint();
    2730             : 
    2731           0 :     const sal_uLong nSttNd = pStt->nNode.GetIndex();
    2732           0 :     const sal_uLong nEndNd = pEnd->nNode.GetIndex();
    2733             : 
    2734           0 :     const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
    2735           0 :     const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
    2736             : 
    2737           0 :     const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
    2738           0 :     if( pStt == pEnd && pTNd )                  // no region ?
    2739             :     {
    2740             :         // do nothing
    2741           0 :         return;
    2742             :     }
    2743             : 
    2744           0 :     if( nSttNd != nEndNd )
    2745             :     {
    2746           0 :         SwNodeIndex aIdx( pStt->nNode );
    2747           0 :         if( nSttCnt )
    2748             :         {
    2749           0 :             ++aIdx;
    2750           0 :             if( pTNd )
    2751           0 :                 pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().Len() );
    2752             :         }
    2753             : 
    2754           0 :         for( ; aIdx.GetIndex() < nEndNd; ++aIdx )
    2755           0 :             if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
    2756           0 :                 pTNd->CountWords( rStat, 0, pTNd->GetTxt().Len() );
    2757             : 
    2758           0 :         if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
    2759           0 :             pTNd->CountWords( rStat, 0, nEndCnt );
    2760             :     }
    2761           0 :     else if( pTNd && nSttCnt < nEndCnt )
    2762           0 :         pTNd->CountWords( rStat, nSttCnt, nEndCnt );
    2763             : }
    2764             : 
    2765           0 : void SwDoc::RemoveLeadingWhiteSpace(const SwPosition & rPos )
    2766             : {
    2767           0 :     const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
    2768           0 :     if ( pTNd )
    2769             :     {
    2770           0 :         const String& rTxt = pTNd->GetTxt();
    2771           0 :         xub_StrLen nIdx = 0;
    2772             :         sal_Unicode cCh;
    2773           0 :         while( nIdx < rTxt.Len() &&
    2774           0 :                 ( '\t' == ( cCh = rTxt.GetChar( nIdx ) ) ||
    2775             :                 (  ' ' == cCh ) ) )
    2776           0 :             ++nIdx;
    2777             : 
    2778           0 :         if ( nIdx > 0 )
    2779             :         {
    2780           0 :             SwPaM aPam(rPos);
    2781           0 :             aPam.GetPoint()->nContent = 0;
    2782           0 :             aPam.SetMark();
    2783           0 :             aPam.GetMark()->nContent = nIdx;
    2784           0 :             DeleteRange( aPam );
    2785             :         }
    2786             :     }
    2787           0 : }
    2788             : 
    2789             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10