LCOV - code coverage report
Current view: top level - sw/source/core/docnode - ndcopy.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 527 789 66.8 %
Date: 2014-04-11 Functions: 19 21 90.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <editeng/formatbreakitem.hxx>
      21             : 
      22             : #include <hintids.hxx>
      23             : #include <fmtpdsc.hxx>
      24             : #include <fmtanchr.hxx>
      25             : #include <fmtcntnt.hxx>
      26             : #include <doc.hxx>
      27             : #include <IDocumentUndoRedo.hxx>
      28             : #include <pam.hxx>
      29             : #include <ndtxt.hxx>
      30             : #include <fldbas.hxx>
      31             : #include <swtable.hxx>
      32             : #include <ddefld.hxx>
      33             : #include <unocrsr.hxx>
      34             : #include <undobj.hxx>
      35             : #include <IMark.hxx>
      36             : #include <mvsave.hxx>
      37             : #include <cellatr.hxx>
      38             : #include <swtblfmt.hxx>
      39             : #include <swddetbl.hxx>
      40             : #include <docary.hxx>
      41             : #include <fmtcnct.hxx>
      42             : #include <redline.hxx>
      43             : #include <paratr.hxx>
      44             : #include <pagedesc.hxx>
      45             : #include <poolfmt.hxx>
      46             : #include <SwNodeNum.hxx>
      47             : #include <set>
      48             : #include <vector>
      49             : #include <boost/foreach.hpp>
      50             : 
      51             : #ifdef DBG_UTIL
      52             : #define CHECK_TABLE(t) (t).CheckConsistency();
      53             : #else
      54             : #define CHECK_TABLE(t)
      55             : #endif
      56             : 
      57             : namespace
      58             : {
      59             :     /*
      60             :         The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
      61             :         array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
      62             :         every node (at least at the moment: 2/08/2006 ), section start and end nodes will not be copied if the corresponding end/start node is outside the copied pam.
      63             :         The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
      64             :         index inside the pam.
      65             :         rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
      66             :         of "non-copy" nodes between rPam.Start() and rLastIdx.
      67             :         nNewIdx is the new position of interest.
      68             :     */
      69             : 
      70         359 :     static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
      71             :     {
      72         359 :         sal_uLong nStart = rPam.Start()->nNode.GetIndex();
      73         359 :         sal_uLong nEnd = rPam.End()->nNode.GetIndex();
      74         359 :         if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
      75             :         {
      76         690 :             do // count "non-copy" nodes
      77             :             {
      78         690 :                 SwNode& rNode = rLastIdx.GetNode();
      79        1380 :                 if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
      80        1380 :                     || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
      81           0 :                     ++rDelCount;
      82         690 :                 ++rLastIdx;
      83             :             }
      84         690 :             while( rLastIdx.GetIndex() < nNewIdx );
      85             :         }
      86         150 :         else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
      87             :                              // no move backward needed
      88             :         {
      89           0 :             while( rLastIdx.GetIndex() > nNewIdx )
      90             :             {
      91           0 :                 SwNode& rNode = rLastIdx.GetNode();
      92           0 :                 if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
      93           0 :                     || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
      94           0 :                     --rDelCount;
      95           0 :                 rLastIdx--;
      96             :             }
      97             :         }
      98         359 :     }
      99             : 
     100         359 :     static void lcl_SetCpyPos( const SwPosition& rOrigPos,
     101             :                         const SwPosition& rOrigStt,
     102             :                         const SwPosition& rCpyStt,
     103             :                         SwPosition& rChgPos,
     104             :                         sal_uLong nDelCount )
     105             :     {
     106         359 :         sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
     107         359 :         nNdOff -= rOrigStt.nNode.GetIndex();
     108         359 :         nNdOff -= nDelCount;
     109         359 :         sal_Int32 nCntntPos = rOrigPos.nContent.GetIndex();
     110             : 
     111             :         // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
     112         359 :         rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
     113         359 :         if( !nNdOff )
     114             :         {
     115             :             // dann nur den Content anpassen
     116           0 :             if( nCntntPos > rOrigStt.nContent.GetIndex() )
     117           0 :                 nCntntPos -= rOrigStt.nContent.GetIndex();
     118             :             else
     119           0 :                 nCntntPos = 0;
     120           0 :             nCntntPos += rCpyStt.nContent.GetIndex();
     121             :         }
     122         359 :         rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
     123         359 :     }
     124             : 
     125             :     // TODO: use SaveBookmark (from _DelBookmarks)
     126         210 :     static void lcl_CopyBookmarks(
     127             :         const SwPaM& rPam,
     128             :         SwPaM& rCpyPam )
     129             :     {
     130         210 :         const SwDoc* pSrcDoc = rPam.GetDoc();
     131         210 :         SwDoc* pDestDoc =  rCpyPam.GetDoc();
     132         210 :         const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
     133         210 :         ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
     134             : 
     135         210 :         const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
     136         210 :         SwPosition* pCpyStt = rCpyPam.Start();
     137             : 
     138             :         typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
     139         420 :         mark_vector_t vMarksToCopy;
     140       32799 :         for ( IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getAllMarksBegin();
     141       21866 :               ppMark != pSrcMarkAccess->getAllMarksEnd();
     142             :               ++ppMark )
     143             :         {
     144       10723 :             const ::sw::mark::IMark* const pMark = ppMark->get();
     145             : 
     146       10723 :             const SwPosition& rMarkStart = pMark->GetMarkStart();
     147       10723 :             const SwPosition& rMarkEnd = pMark->GetMarkEnd();
     148             :             // only include marks that are in the range and not touching both start and end
     149             :             // - not for annotation marks.
     150             :             const bool bIsNotOnBoundary =
     151       10723 :                 pMark->IsExpanded()
     152        1513 :                 ? (rMarkStart != rStt || rMarkEnd != rEnd)  // rMarkStart != rMarkEnd
     153       12236 :                 : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
     154       31951 :             if ( rMarkStart >= rStt && rMarkEnd <= rEnd
     155       11503 :                  && ( bIsNotOnBoundary
     156          62 :                       || IDocumentMarkAccess::GetType( *pMark ) == IDocumentMarkAccess::ANNOTATIONMARK ) )
     157             :             {
     158         359 :                 vMarksToCopy.push_back(pMark);
     159             :             }
     160             :         }
     161             :         // We have to count the "non-copied" nodes..
     162         420 :         SwNodeIndex aCorrIdx(rStt.nNode);
     163         210 :         sal_uLong nDelCount = 0;
     164        1707 :         for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
     165        1138 :             ppMark != vMarksToCopy.end();
     166             :             ++ppMark)
     167             :         {
     168         359 :             const ::sw::mark::IMark* const pMark = *ppMark;
     169         359 :             SwPaM aTmpPam(*pCpyStt);
     170         359 :             lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
     171         359 :             lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
     172         359 :             if(pMark->IsExpanded())
     173             :             {
     174           0 :                 aTmpPam.SetMark();
     175           0 :                 lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
     176           0 :                 lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
     177             :             }
     178             : 
     179         359 :             ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
     180             :                 aTmpPam,
     181         359 :                 pMark->GetName(),
     182         718 :                 IDocumentMarkAccess::GetType(*pMark));
     183             :             // Explicitly try to get exactly the same name as in the source
     184             :             // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
     185         359 :             pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
     186             : 
     187             :             // copying additional attributes for bookmarks or fieldmarks
     188             :             ::sw::mark::IBookmark* const pNewBookmark =
     189         359 :                 dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
     190         359 :             if(pNewBookmark)
     191             :             {
     192           1 :                 const ::sw::mark::IBookmark* const pOldBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
     193           1 :                 pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
     194           1 :                 pNewBookmark->SetShortName(pOldBookmark->GetShortName());
     195             :             }
     196             :             ::sw::mark::IFieldmark* const pNewFieldmark =
     197         359 :                 dynamic_cast< ::sw::mark::IFieldmark* const >(pNewMark);
     198         359 :             if(pNewFieldmark)
     199             :             {
     200           0 :                 const ::sw::mark::IFieldmark* const pOldFieldmark = dynamic_cast< const ::sw::mark::IFieldmark* >(pMark);
     201           0 :                 pNewFieldmark->SetFieldname(pOldFieldmark->GetFieldname());
     202           0 :                 pNewFieldmark->SetFieldHelptext(pOldFieldmark->GetFieldHelptext());
     203           0 :                 ::sw::mark::IFieldmark::parameter_map_t* pNewParams = pNewFieldmark->GetParameters();
     204           0 :                 const ::sw::mark::IFieldmark::parameter_map_t* pOldParams = pOldFieldmark->GetParameters();
     205           0 :                 ::sw::mark::IFieldmark::parameter_map_t::const_iterator pIt = pOldParams->begin();
     206           0 :                 for (; pIt != pOldParams->end(); ++pIt )
     207             :                 {
     208           0 :                     pNewParams->insert( *pIt );
     209             :                 }
     210             :             }
     211             : 
     212             :             ::sfx2::Metadatable const*const pMetadatable(
     213         359 :                     dynamic_cast< ::sfx2::Metadatable const* >(pMark));
     214             :             ::sfx2::Metadatable      *const pNewMetadatable(
     215         359 :                     dynamic_cast< ::sfx2::Metadatable      * >(pNewMark));
     216         359 :             if (pMetadatable && pNewMetadatable)
     217             :             {
     218           1 :                 pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
     219             :             }
     220         569 :         }
     221         210 :     }
     222             : }
     223             : 
     224             : // Structure for the mapping from old and new frame formats to the
     225             : // boxes and lines of a table
     226             : struct _MapTblFrmFmt
     227             : {
     228             :     const SwFrmFmt *pOld, *pNew;
     229        1278 :     _MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
     230        1278 :         : pOld( pOldFmt ), pNew( pNewFmt )
     231        1278 :     {}
     232             : };
     233             : 
     234             : typedef std::vector<_MapTblFrmFmt> _MapTblFrmFmts;
     235             : 
     236        3572 : SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
     237             : {
     238             :     // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
     239             :     // node with the collection and hard attributes. Normally is the same
     240             :     // node, but if insert a glossary without formatting, then the Attrnode
     241             :     // is the prev node of the destionation position in dest. document.
     242        3572 :     SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
     243        3572 :     SwTxtNode* pCpyAttrNd = pCpyTxtNd;
     244             : 
     245             :     // Copy the formats to the other document
     246        3572 :     SwTxtFmtColl* pColl = 0;
     247        3572 :     if( pDoc->IsInsOnlyTextGlossary() )
     248             :     {
     249           2 :         SwNodeIndex aIdx( rIdx, -1 );
     250           2 :         if( aIdx.GetNode().IsTxtNode() )
     251             :         {
     252           2 :             pCpyAttrNd = aIdx.GetNode().GetTxtNode();
     253           2 :             pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
     254           2 :         }
     255             :     }
     256        3572 :     if( !pColl )
     257        3570 :         pColl = pDoc->CopyTxtColl( *GetTxtColl() );
     258             : 
     259        3572 :     SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
     260             : 
     261             :     // METADATA: register copy
     262        3572 :     pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
     263             : 
     264             :     // Copy Attribute/Text
     265        3572 :     if( !pCpyAttrNd->HasSwAttrSet() )
     266             :         // An AttrSet was added for numbering, so delete it
     267        1878 :         pTxtNd->ResetAllAttr();
     268             : 
     269             :     // if Copy-Textnode unequal to Copy-Attrnode, then copy first
     270             :     // the attributes into the new Node.
     271        3572 :     if( pCpyAttrNd != pCpyTxtNd )
     272             :     {
     273           2 :         pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
     274           2 :         if( pCpyAttrNd->HasSwAttrSet() )
     275             :         {
     276           0 :             SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
     277           0 :             aSet.ClearItem( RES_PAGEDESC );
     278           0 :             aSet.ClearItem( RES_BREAK );
     279           0 :             aSet.CopyToModify( *pTxtNd );
     280             :         }
     281             :     }
     282             : 
     283             :     // Is that enough? What about PostIts/Fields/FieldTypes?
     284             :     // #i96213# - force copy of all attributes
     285        3572 :     pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
     286        7144 :         pCpyTxtNd->GetTxt().getLength(), true );
     287             : 
     288        3572 :     if( RES_CONDTXTFMTCOLL == pColl->Which() )
     289           0 :         pTxtNd->ChkCondColl();
     290             : 
     291        3572 :     return pTxtNd;
     292             : }
     293             : 
     294        6875 : static bool lcl_SrchNew( const _MapTblFrmFmt& rMap, const SwFrmFmt** pPara )
     295             : {
     296        6875 :     if( rMap.pOld != *pPara )
     297        6875 :         return true;
     298           0 :     *pPara = rMap.pNew;
     299           0 :     return false;
     300             : }
     301             : 
     302             : struct _CopyTable
     303             : {
     304             :     SwDoc* pDoc;
     305             :     sal_uLong nOldTblSttIdx;
     306             :     _MapTblFrmFmts& rMapArr;
     307             :     SwTableLine* pInsLine;
     308             :     SwTableBox* pInsBox;
     309             :     SwTableNode *pTblNd;
     310             :     const SwTable *pOldTable;
     311             : 
     312         197 :     _CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
     313             :                 SwTableNode& rTblNd, const SwTable* pOldTbl )
     314             :         : pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
     315         197 :         pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
     316         197 :     {}
     317             : };
     318             : 
     319             : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT );
     320             : 
     321         931 : static void lcl_CopyTblBox( SwTableBox* pBox, _CopyTable* pCT )
     322             : {
     323         931 :     SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
     324        6519 :     for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
     325        5588 :         if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pBoxFmt ) )
     326           0 :             break;
     327         931 :     if( pBoxFmt == pBox->GetFrmFmt() ) // Create a new one?
     328             :     {
     329             :         const SfxPoolItem* pItem;
     330         931 :         if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, sal_False,
     331         931 :             &pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
     332             :         {
     333           0 :             ((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
     334             :         }
     335             : 
     336         931 :         pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
     337         931 :         pBoxFmt->CopyAttrs( *pBox->GetFrmFmt() );
     338             : 
     339         931 :         if( pBox->GetSttIdx() )
     340             :         {
     341         931 :             SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( sal_False );
     342         931 :             if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
     343           0 :                 GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
     344             :             {
     345           0 :                 sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
     346           0 :                 sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
     347           0 :                 if( nNewIdx != nOldIdx )
     348           0 :                     pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
     349             : 
     350             :             }
     351             :         }
     352             : 
     353         931 :         pCT->rMapArr.push_back( _MapTblFrmFmt( pBox->GetFrmFmt(), pBoxFmt ) );
     354             :     }
     355             : 
     356         931 :     sal_uInt16 nLines = pBox->GetTabLines().size();
     357             :     SwTableBox* pNewBox;
     358         931 :     if( nLines )
     359           0 :         pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
     360             :     else
     361             :     {
     362             :         SwNodeIndex aNewIdx( *pCT->pTblNd,
     363         931 :                             pBox->GetSttIdx() - pCT->nOldTblSttIdx );
     364             :         OSL_ENSURE( aNewIdx.GetNode().IsStartNode(), "Index is not on the start node" );
     365         931 :         pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
     366         931 :         pNewBox->setRowSpan( pBox->getRowSpan() );
     367             :     }
     368             : 
     369         931 :     pCT->pInsLine->GetTabBoxes().push_back( pNewBox );
     370             : 
     371         931 :     if( nLines )
     372             :     {
     373           0 :         _CopyTable aPara( *pCT );
     374           0 :         aPara.pInsBox = pNewBox;
     375           0 :         BOOST_FOREACH( const SwTableLine* pLine, pBox->GetTabLines() )
     376           0 :             lcl_CopyTblLine( pLine, &aPara );
     377             :     }
     378         931 :     else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
     379             :         // In the headline, the paragraphs must match conditional styles
     380         444 :         pNewBox->GetSttNd()->CheckSectionCondColl();
     381         931 : }
     382             : 
     383         347 : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT )
     384             : {
     385         347 :     SwTableLineFmt* pLineFmt = (SwTableLineFmt*)pLine->GetFrmFmt();
     386        1634 :     for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
     387        1287 :         if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pLineFmt ) )
     388           0 :             break;
     389         347 :     if( pLineFmt == pLine->GetFrmFmt() ) // Create a new one?
     390             :     {
     391         347 :         pLineFmt = pCT->pDoc->MakeTableLineFmt();
     392         347 :         pLineFmt->CopyAttrs( *pLine->GetFrmFmt() );
     393         347 :         pCT->rMapArr.push_back( _MapTblFrmFmt( pLine->GetFrmFmt(), pLineFmt ) );
     394             :     }
     395             :     SwTableLine* pNewLine = new SwTableLine( pLineFmt,
     396         347 :                             pLine->GetTabBoxes().size(), pCT->pInsBox );
     397             :     // Insert the new row into the table
     398         347 :     if( pCT->pInsBox )
     399             :     {
     400           0 :         pCT->pInsBox->GetTabLines().push_back( pNewLine );
     401             :     }
     402             :     else
     403             :     {
     404         347 :         pCT->pTblNd->GetTable().GetTabLines().push_back( pNewLine );
     405             :     }
     406         347 :     pCT->pInsLine = pNewLine;
     407        3834 :     for( SwTableBoxes::iterator it = ((SwTableLine*)pLine)->GetTabBoxes().begin();
     408        2556 :              it != ((SwTableLine*)pLine)->GetTabBoxes().end(); ++it)
     409         931 :         lcl_CopyTblBox(*it, pCT );
     410         347 : }
     411             : 
     412         197 : SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
     413             : {
     414             :     // In which array are we? Nodes? UndoNodes?
     415         197 :     SwNodes& rNds = (SwNodes&)GetNodes();
     416             : 
     417             :     {
     418         197 :         if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
     419           0 :             rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
     420           0 :             return 0;
     421             :     }
     422             : 
     423             :     // Copy the TableFrmFmt
     424         197 :     OUString sTblName( GetTable().GetFrmFmt()->GetName() );
     425         197 :     if( !pDoc->IsCopyIsMove() )
     426             :     {
     427         168 :         const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
     428         728 :         for( sal_uInt16 n = rTblFmts.size(); n; )
     429         559 :             if( rTblFmts[ --n ]->GetName() == sTblName )
     430             :             {
     431         167 :                 sTblName = pDoc->GetUniqueTblName();
     432         167 :                 break;
     433             :             }
     434             :     }
     435             : 
     436         197 :     SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
     437         197 :     pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
     438         197 :     SwTableNode* pTblNd = new SwTableNode( rIdx );
     439         197 :     SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
     440         394 :     SwNodeIndex aInsPos( *pEndNd );
     441             : 
     442         197 :     SwTable& rTbl = (SwTable&)pTblNd->GetTable();
     443         197 :     rTbl.RegisterToFormat( *pTblFmt );
     444             : 
     445         197 :     rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
     446         197 :     rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
     447         197 :     rTbl.SetTableModel( GetTable().IsNewModel() );
     448             : 
     449         197 :     SwDDEFieldType* pDDEType = 0;
     450         197 :     if( IS_TYPE( SwDDETable, &GetTable() ))
     451             :     {
     452             :         // We're copying a DDE table
     453             :         // Is the field type available in the new document?
     454           0 :         pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
     455           0 :         if( pDDEType->IsDeleted() )
     456           0 :             pDoc->InsDeletedFldType( *pDDEType );
     457             :         else
     458           0 :             pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
     459             :         OSL_ENSURE( pDDEType, "unknown FieldType" );
     460             : 
     461             :         // Swap the table pointers in the node
     462           0 :         SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
     463           0 :         pTblNd->SetNewTable( pNewTable, sal_False );
     464             :     }
     465             :     // First copy the content of the tables, we will later assign the
     466             :     // boxes/lines and create the frames
     467         394 :     SwNodeRange aRg( *this, +1, *EndOfSectionNode() );
     468             : 
     469             :     // If there is a table in this table, the table format for the outer table
     470             :     // does not seem to be used, because the table does not have any contents yet
     471             :     // (see IsUsed). Therefore the inner table gets the same name as the outer table.
     472             :     // We have to make sure that the table node of the SwTable is accessible, even
     473             :     // without any content in m_TabSortContentBoxes. #i26629#
     474         197 :     pTblNd->GetTable().SetTableNode( pTblNd );
     475         197 :     rNds._Copy( aRg, aInsPos, sal_False );
     476         197 :     pTblNd->GetTable().SetTableNode( 0 );
     477             : 
     478             :     // Special case for a single box
     479         197 :     if( 1 == GetTable().GetTabSortBoxes().size() )
     480             :     {
     481          13 :         aRg.aStart.Assign( *pTblNd, 1 );
     482          13 :         aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
     483          13 :         pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
     484             :     }
     485             : 
     486             :     // Delete all frames from the copied area, they will be created
     487             :     // during the generation of the table frame
     488         197 :     pTblNd->DelFrms();
     489             : 
     490         394 :     _MapTblFrmFmts aMapArr;
     491         197 :     _CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
     492             : 
     493         544 :     BOOST_FOREACH(const SwTableLine* pLine, GetTable().GetTabLines() )
     494         347 :         lcl_CopyTblLine( pLine, &aPara );
     495             : 
     496         197 :     if( pDDEType )
     497           0 :         pDDEType->IncRefCnt();
     498             : 
     499             :     CHECK_TABLE( GetTable() );
     500         394 :     return pTblNd;
     501             : }
     502             : 
     503          98 : void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
     504             : {
     505             :     // Copy the formats into the other document:
     506             :     // Special case for PageBreak/PageDesc/ColBrk
     507          98 :     SwDoc* pDestDoc = rDestNd.GetDoc();
     508          98 :     SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
     509             :     const SwAttrSet* pSet;
     510             : 
     511          98 :     if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
     512             :     {
     513             :         // Special cases for Break-Attributes
     514             :         const SfxPoolItem* pAttr;
     515          67 :         if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pAttr ) )
     516           0 :             aPgBrkSet.Put( *pAttr );
     517             : 
     518          67 :         if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pAttr ) )
     519           0 :             aPgBrkSet.Put( *pAttr );
     520             :     }
     521             : 
     522          98 :     rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
     523          98 :     if( 0 != ( pSet = GetpSwAttrSet() ) )
     524          67 :         pSet->CopyToModify( rDestNd );
     525             : 
     526          98 :     if( aPgBrkSet.Count() )
     527           0 :         rDestNd.SetAttr( aPgBrkSet );
     528          98 : }
     529             : 
     530             : // Copy method from SwDoc
     531             : // Prevent copying in Flys that are anchored in the area
     532         109 : static sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
     533             :                         sal_uLong nInsNd )
     534             : {
     535         109 :     const SwFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
     536             : 
     537        1346 :     for( sal_uInt16 n = 0; n < rFrmFmtTbl.size(); ++n )
     538             :     {
     539        1237 :         SwFrmFmt const*const  pFmt = rFrmFmtTbl[n];
     540        1237 :         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
     541        1237 :         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
     542        2398 :         if (pAPos &&
     543        1855 :             ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
     544        1338 :              (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
     545        1288 :              (FLY_AT_FLY  == pAnchor->GetAnchorId()) ||
     546        1805 :              (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
     547        3190 :             nSttNd <= pAPos->nNode.GetIndex() &&
     548         792 :             pAPos->nNode.GetIndex() < nEndNd )
     549             :         {
     550          24 :             const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
     551             :             SwStartNode* pSNd;
     552          40 :             if( !rCntnt.GetCntntIdx() ||
     553          16 :                 0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
     554           8 :                 continue;
     555             : 
     556          32 :             if( pSNd->GetIndex() < nInsNd &&
     557          16 :                 nInsNd < pSNd->EndOfSectionIndex() )
     558             :                 // Do not copy !
     559           0 :                 return sal_True;
     560             : 
     561          16 :             if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
     562          16 :                         pSNd->EndOfSectionIndex(), nInsNd ) )
     563             :                 // Do not copy !
     564           0 :                 return sal_True;
     565             :         }
     566             :     }
     567             : 
     568         109 :     return sal_False;
     569             : }
     570             : 
     571           2 : static void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
     572             : {
     573           2 :     const SwDoc* pSrcDoc = rPam.GetDoc();
     574           2 :     const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
     575           2 :     if( !rTbl.empty() )
     576             :     {
     577           0 :         SwDoc* pDestDoc = rCpyPam.GetDoc();
     578           0 :         SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
     579           0 :         SwPaM* pDelPam = 0;
     580           0 :         const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
     581             :         // We have to count the "non-copied" nodes
     582           0 :         sal_uLong nDelCount = 0;
     583           0 :         SwNodeIndex aCorrIdx( pStt->nNode );
     584             : 
     585           0 :         sal_uInt16 n = 0;
     586           0 :         pSrcDoc->GetRedline( *pStt, &n );
     587           0 :         for( ; n < rTbl.size(); ++n )
     588             :         {
     589           0 :             const SwRangeRedline* pRedl = rTbl[ n ];
     590           0 :             if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
     591             :             {
     592           0 :                 const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
     593             : 
     594           0 :                 SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
     595           0 :                 switch( eCmpPos )
     596             :                 {
     597             :                 case POS_COLLIDE_END:
     598             :                 case POS_BEFORE:
     599             :                     // Pos1 is before Pos2
     600           0 :                     break;
     601             : 
     602             :                 case POS_COLLIDE_START:
     603             :                 case POS_BEHIND:
     604             :                     // Pos1 is after Pos2
     605           0 :                     n = rTbl.size();
     606           0 :                     break;
     607             : 
     608             :                 default:
     609             :                     {
     610           0 :                         pDelPam = new SwPaM( *pCpyStt, pDelPam );
     611           0 :                         if( *pStt < *pRStt )
     612             :                         {
     613           0 :                             lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
     614             :                             lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
     615           0 :                                             *pDelPam->GetPoint(), nDelCount );
     616             :                         }
     617           0 :                         pDelPam->SetMark();
     618             : 
     619           0 :                         if( *pEnd < *pREnd )
     620           0 :                             *pDelPam->GetPoint() = *pCpyEnd;
     621             :                         else
     622             :                         {
     623           0 :                             lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
     624             :                             lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
     625           0 :                                             *pDelPam->GetPoint(), nDelCount );
     626             :                         }
     627             :                     }
     628             :                 }
     629             :             }
     630             :         }
     631             : 
     632           0 :         if( pDelPam )
     633             :         {
     634           0 :             RedlineMode_t eOld = pDestDoc->GetRedlineMode();
     635           0 :             pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
     636             : 
     637           0 :             ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
     638             : 
     639             :             do {
     640           0 :                 pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
     641           0 :                 if( pDelPam->GetNext() == pDelPam )
     642           0 :                     break;
     643           0 :                 delete pDelPam->GetNext();
     644             :             } while( true );
     645           0 :             delete pDelPam;
     646             : 
     647           0 :             pDestDoc->SetRedlineMode_intern( eOld );
     648           0 :         }
     649             :     }
     650           2 : }
     651             : 
     652           0 : static void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
     653             : {
     654           0 :     SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
     655           0 :     if( !pSrcDoc->GetRedlineTbl().empty() )
     656             :     {
     657           0 :         SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
     658           0 :         SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
     659           0 :         lcl_DeleteRedlines( aRgTmp, aCpyTmp );
     660             :     }
     661           0 : }
     662             : 
     663             : // Copy an area into this document or into another document
     664             : bool
     665         131 : SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
     666             : {
     667         131 :     const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
     668             : 
     669         131 :     SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
     670         131 :     bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
     671             : 
     672             :     // Catch if there's no copy to do
     673         131 :     if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
     674          29 :         return false;
     675             : 
     676             :     // Prevent copying in Flys that are anchored in the area
     677         102 :     if( pDoc == this )
     678             :     {
     679             :         // Correct the Start-/EndNode
     680          94 :         sal_uLong nStt = pStt->nNode.GetIndex(),
     681          94 :                 nEnd = pEnd->nNode.GetIndex(),
     682          94 :                 nDiff = nEnd - nStt +1;
     683          94 :         SwNode* pNd = GetNodes()[ nStt ];
     684          94 :         if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
     685           1 :             ++nStt, --nDiff;
     686         188 :         if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
     687          94 :             ((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
     688           0 :             --nEnd, --nDiff;
     689         187 :         if( nDiff &&
     690          93 :             lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
     691             :         {
     692           0 :             return false;
     693             :         }
     694             :     }
     695             : 
     696         102 :     SwPaM* pRedlineRange = 0;
     697         209 :     if( pDoc->IsRedlineOn() ||
     698         203 :         (!pDoc->IsIgnoreRedline() && !pDoc->GetRedlineTbl().empty() ) )
     699           5 :         pRedlineRange = new SwPaM( rPos );
     700             : 
     701         102 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     702             : 
     703         102 :     bool bRet = false;
     704             : 
     705         102 :     if( pDoc != this )
     706             :     {   // ordinary copy
     707           8 :         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
     708             :     }
     709         227 :     else if( ! ( *pStt <= rPos && rPos < *pEnd &&
     710           0 :             ( pStt->nNode != pEnd->nNode ||
     711         188 :               !pStt->nNode.GetNode().IsTxtNode() )) )
     712             :     {
     713             :         // Copy to a position outside of the area, or copy a single TextNode
     714             :         // Do an ordinary copy
     715          94 :         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
     716             :     }
     717             :     else
     718             :     {
     719             :         // Copy the area in itself
     720             :         // Special case for handling an area with several nodes,
     721             :         // or a single node that is not a TextNode
     722             :         OSL_ENSURE( this == pDoc, " invalid copy branch!" );
     723             :         OSL_FAIL("mst: i thought this could be dead code;"
     724             :                 "please tell me what you did to get here!");
     725           0 :         pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
     726             : 
     727             :         // Then copy the area to the underlying document area
     728             :         // (with start/end nodes clamped) and move them to
     729             :         // the desired position.
     730             : 
     731           0 :         SwUndoCpyDoc* pUndo = 0;
     732             :         // Save the Undo area
     733           0 :         SwPaM aPam( rPos );
     734           0 :         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
     735             :         {
     736           0 :             pDoc->GetIDocumentUndoRedo().ClearRedo();
     737           0 :             pUndo = new SwUndoCpyDoc( aPam );
     738             :         }
     739             : 
     740             :         {
     741           0 :             ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
     742           0 :             SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
     743           0 :                                 SwNodeIndex( GetNodes().GetEndOfAutotext() ));
     744           0 :             aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
     745             :             // copy without Frames
     746           0 :             pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
     747             : 
     748           0 :             aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
     749           0 :             aPam.SetMark();
     750             :             SwCntntNode* pNode =
     751           0 :                 pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
     752           0 :             pNode->MakeEndIndex( &aPam.GetMark()->nContent );
     753             : 
     754           0 :             aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
     755           0 :             pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
     756           0 :             pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
     757             :             // move to desired position
     758           0 :             pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
     759             : 
     760           0 :             pNode = aPam.GetCntntNode();
     761           0 :             *aPam.GetPoint() = rPos;      // Move the cursor for Undo
     762           0 :             aPam.SetMark();               // also move the Mark
     763           0 :             aPam.DeleteMark();            // But don't mark any area
     764           0 :             pDoc->DeleteSection( pNode ); // Delete the area again
     765             :         }
     766             : 
     767             :         // if Undo is enabled, store the insertion range
     768           0 :         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
     769             :         {
     770           0 :             pUndo->SetInsertRange( aPam );
     771           0 :             pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
     772             :         }
     773             : 
     774           0 :         if( pRedlineRange )
     775             :         {
     776           0 :             pRedlineRange->SetMark();
     777           0 :             *pRedlineRange->GetPoint() = *aPam.GetPoint();
     778           0 :             *pRedlineRange->GetMark() = *aPam.GetMark();
     779             :         }
     780             : 
     781           0 :         pDoc->SetModified();
     782           0 :         bRet = true;
     783             :     }
     784             : 
     785         102 :     pDoc->SetRedlineMode_intern( eOld );
     786         102 :     if( pRedlineRange )
     787             :     {
     788           5 :         if( pDoc->IsRedlineOn() )
     789           0 :             pDoc->AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
     790             :         else
     791           5 :             pDoc->SplitRedline( *pRedlineRange );
     792           5 :         delete pRedlineRange;
     793             :     }
     794             : 
     795         102 :     return bRet;
     796             : }
     797             : 
     798          30 : static bool lcl_MarksWholeNode(const SwPaM & rPam)
     799             : {
     800          30 :     bool bResult = false;
     801          30 :     const SwPosition* pStt = rPam.Start();
     802          30 :     const SwPosition* pEnd = rPam.End();
     803             : 
     804          30 :     if (NULL != pStt && NULL != pEnd)
     805             :     {
     806          30 :         const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
     807          30 :         const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
     808             : 
     809          90 :         if (NULL != pSttNd && NULL != pEndNd &&
     810          88 :             pStt->nContent.GetIndex() == 0 &&
     811          28 :             pEnd->nContent.GetIndex() == pEndNd->Len())
     812             :         {
     813          28 :             bResult = true;
     814             :         }
     815             :     }
     816             : 
     817          30 :     return bResult;
     818             : }
     819             : 
     820             : // #i86492#
     821           2 : static bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
     822             : {
     823           2 :     bool bRet = false;
     824             : 
     825           2 :     const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
     826           2 :     const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
     827           4 :     if ( pTxtNd && pTxtNd->IsInList() &&
     828           3 :          pEndTxtNd && pEndTxtNd->IsInList() )
     829             :     {
     830           1 :         bRet = true;
     831           1 :         SwNodeIndex aIdx(rPam.Start()->nNode);
     832             : 
     833           0 :         do
     834             :         {
     835           1 :             ++aIdx;
     836           1 :             pTxtNd = aIdx.GetNode().GetTxtNode();
     837             : 
     838           1 :             if ( !pTxtNd || !pTxtNd->IsInList() )
     839             :             {
     840           1 :                 bRet = false;
     841           1 :                 break;
     842             :             }
     843           0 :         } while ( pTxtNd && pTxtNd != pEndTxtNd );
     844             :     }
     845             : 
     846           2 :     return bRet;
     847             : }
     848             : 
     849         102 : bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
     850             :         const bool bMakeNewFrms, const bool bCopyAll,
     851             :         SwPaM *const pCpyRange ) const
     852             : {
     853         102 :     SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
     854         102 :     const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
     855             : 
     856         102 :     SwPosition* pStt = rPam.Start();
     857         102 :     SwPosition* pEnd = rPam.End();
     858             : 
     859             :     // Catch when there's no copy to do.
     860         102 :     if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
     861             :         //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
     862             :         //JP 15.11.2001: don't test inclusive the end, ever exclusive
     863          94 :         ( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
     864             :     {
     865           0 :         return false;
     866             :     }
     867             : 
     868         102 :     const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
     869             : 
     870             :     // If Undo is enabled, create the UndoCopy object
     871         102 :     SwUndoCpyDoc* pUndo = 0;
     872             :     // lcl_DeleteRedlines may delete the start or end node of the cursor when
     873             :     // removing the redlines so use cursor that is corrected by PaMCorrAbs
     874         102 :     ::boost::scoped_ptr<SwUnoCrsr> const pCopyPam(pDoc->CreateUnoCrsr(rPos));
     875             : 
     876         204 :     SwTblNumFmtMerge aTNFM( *this, *pDoc );
     877             : 
     878         102 :     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
     879             :     {
     880           4 :         pUndo = new SwUndoCpyDoc(*pCopyPam);
     881           4 :         pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
     882             :     }
     883             : 
     884         102 :     RedlineMode_t eOld = pDoc->GetRedlineMode();
     885         102 :     pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
     886             : 
     887             :     // Move the PaM one node back from the insert position, so that
     888             :     // the position doesn't get moved
     889         102 :     pCopyPam->SetMark();
     890         102 :     bool bCanMoveBack = pCopyPam->Move(fnMoveBackward, fnGoCntnt);
     891             :     // If the position was shifted from more than one node, an end node has been skipped
     892         102 :     bool bAfterTable = false;
     893         102 :     if ((rPos.nNode.GetIndex() - pCopyPam->GetPoint()->nNode.GetIndex()) > 1)
     894             :     {
     895             :         // First go back to the original place
     896           0 :         pCopyPam->GetPoint()->nNode = rPos.nNode;
     897           0 :         pCopyPam->GetPoint()->nContent = rPos.nContent;
     898             : 
     899           0 :         bCanMoveBack = false;
     900           0 :         bAfterTable = true;
     901             :     }
     902         102 :     if( !bCanMoveBack )
     903         101 :         pCopyPam->GetPoint()->nNode--;
     904             : 
     905         204 :     SwNodeRange aRg( pStt->nNode, pEnd->nNode );
     906         204 :     SwNodeIndex aInsPos( rPos.nNode );
     907         102 :     const bool bOneNode = pStt->nNode == pEnd->nNode;
     908         102 :     SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
     909         102 :     SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
     910         102 :     SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
     911         199 :     bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
     912          99 :                         ( (pDestTxtNd && !pDestTxtNd->GetTxt().getLength()) ||
     913         104 :                           ( !bOneNode && !rPos.nContent.GetIndex() ) );
     914         102 :     bool bCopyBookmarks = true;
     915         102 :     bool bStartIsTxtNode = 0 != pSttTxtNd;
     916             : 
     917             :     // #i104585# copy outline num rule to clipboard (for ASCII filter)
     918         102 :     if (pDoc->IsClipBoard() && GetOutlineNumRule())
     919             :     {
     920           2 :         pDoc->SetOutlineNumRule(*GetOutlineNumRule());
     921             :     }
     922             : 
     923             :     // #i86492#
     924             :     // Correct the search for a previous list:
     925             :     // First search for non-outline numbering list. Then search for non-outline
     926             :     // bullet list.
     927             :     // Keep also the <ListId> value for possible propagation.
     928         204 :     OUString aListIdToPropagate;
     929             :     const SwNumRule* pNumRuleToPropagate =
     930         102 :         pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
     931         102 :     if ( !pNumRuleToPropagate )
     932             :     {
     933             :         pNumRuleToPropagate =
     934         102 :             pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
     935             :     }
     936             :     // #i86492#
     937             :     // Do not propagate previous found list, if
     938             :     // - destination is an empty paragraph which is not in a list and
     939             :     // - source contains at least one paragraph which is not in a list
     940         104 :     if ( pNumRuleToPropagate &&
     941           4 :          pDestTxtNd && !pDestTxtNd->GetTxt().getLength() &&
     942         106 :          !pDestTxtNd->IsInList() &&
     943           2 :          !lcl_ContainsOnlyParagraphsInList( rPam ) )
     944             :     {
     945           2 :         pNumRuleToPropagate = 0;
     946             :     }
     947             : 
     948             :     // This do/while block is only there so that we can break out of it!
     949             :     do {
     950         102 :         if( pSttTxtNd )
     951             :         {
     952             :             // Don't copy the beginning completely?
     953         101 :             if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
     954             :             {
     955           7 :                 SwIndex aDestIdx( rPos.nContent );
     956           7 :                 bool bCopyOk = false;
     957           7 :                 if( !pDestTxtNd )
     958             :                 {
     959           0 :                     if( pStt->nContent.GetIndex() || bOneNode )
     960           0 :                         pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
     961           0 :                             pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
     962             :                     else
     963             :                     {
     964           0 :                         pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
     965           0 :                         bCopyOk = true;
     966             :                     }
     967           0 :                     aDestIdx.Assign( pDestTxtNd, 0 );
     968           0 :                     bCopyCollFmt = true;
     969             :                 }
     970           7 :                 else if( !bOneNode || bColumnSel )
     971             :                 {
     972           5 :                     const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
     973             :                     {
     974           5 :                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
     975           5 :                         pDoc->SplitNode( rPos, false );
     976             :                     }
     977             : 
     978           5 :                     if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
     979             :                     {
     980             :                         // after the SplitNode, span the CpyPam correctly again
     981           0 :                         pCopyPam->Move( fnMoveBackward, fnGoCntnt );
     982           0 :                         pCopyPam->Move( fnMoveBackward, fnGoCntnt );
     983             :                     }
     984             : 
     985           5 :                     pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
     986             :                     aDestIdx.Assign(
     987           5 :                             pDestTxtNd, pDestTxtNd->GetTxt().getLength());
     988             : 
     989             :                     // Correct the area again
     990           5 :                     if( bEndEqualIns )
     991             :                     {
     992           0 :                         bool bChg = pEnd != rPam.GetPoint();
     993           0 :                         if( bChg )
     994           0 :                             rPam.Exchange();
     995           0 :                         rPam.Move( fnMoveBackward, fnGoCntnt );
     996           0 :                         if( bChg )
     997           0 :                             rPam.Exchange();
     998             : 
     999           0 :                         aRg.aEnd = pEnd->nNode;
    1000           0 :                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
    1001             :                     }
    1002           5 :                     else if( rPos == *pEnd )
    1003             :                     {
    1004             :                         // The end was also moved
    1005           0 :                         pEnd->nNode--;
    1006           0 :                         pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
    1007           0 :                         aRg.aEnd = pEnd->nNode;
    1008           0 :                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
    1009             :                     }
    1010             :                 }
    1011             : 
    1012             :                 // Safe numrule item at destination.
    1013             :                 // #i86492# - Safe also <ListId> item of destination.
    1014           7 :                 int aNumRuleState = SFX_ITEM_UNKNOWN;
    1015          12 :                 SwNumRuleItem aNumRuleItem;
    1016           7 :                 int aListIdState = SFX_ITEM_UNKNOWN;
    1017          12 :                 SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
    1018             :                 {
    1019           7 :                     const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
    1020           7 :                     if (pAttrSet != NULL)
    1021             :                     {
    1022           1 :                         const SfxPoolItem * pItem = NULL;
    1023           1 :                         aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
    1024           1 :                         if (SFX_ITEM_SET == aNumRuleState)
    1025           0 :                             aNumRuleItem = *((SwNumRuleItem *) pItem);
    1026             : 
    1027             :                         aListIdState =
    1028           1 :                             pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
    1029           1 :                         if (SFX_ITEM_SET == aListIdState)
    1030             :                         {
    1031           0 :                             aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
    1032             :                         }
    1033             :                     }
    1034             :                 }
    1035             : 
    1036           7 :                 if( !bCopyOk )
    1037             :                 {
    1038             :                     const sal_Int32 nCpyLen = ( (bOneNode)
    1039           2 :                                            ? pEnd->nContent.GetIndex()
    1040           5 :                                            : pSttTxtNd->GetTxt().getLength())
    1041          14 :                                          - pStt->nContent.GetIndex();
    1042             :                     pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
    1043           7 :                                             pStt->nContent, nCpyLen );
    1044           7 :                     if( bEndEqualIns )
    1045           0 :                         pEnd->nContent -= nCpyLen;
    1046             :                 }
    1047             : 
    1048           7 :                 if( bOneNode )
    1049             :                 {
    1050           2 :                     if( bCopyCollFmt )
    1051             :                     {
    1052           2 :                         pSttTxtNd->CopyCollFmt( *pDestTxtNd );
    1053             : 
    1054             :                         /* If only a part of one paragraph is copied
    1055             :                            restore the numrule at the destination. */
    1056             :                         // #i86492# - restore also <ListId> item
    1057           2 :                         if ( !lcl_MarksWholeNode(rPam) )
    1058             :                         {
    1059           2 :                             if (SFX_ITEM_SET == aNumRuleState)
    1060             :                             {
    1061           0 :                                 pDestTxtNd->SetAttr(aNumRuleItem);
    1062             :                             }
    1063             :                             else
    1064             :                             {
    1065           2 :                                 pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
    1066             :                             }
    1067           2 :                             if (SFX_ITEM_SET == aListIdState)
    1068             :                             {
    1069           0 :                                 pDestTxtNd->SetAttr(aListIdItem);
    1070             :                             }
    1071             :                             else
    1072             :                             {
    1073           2 :                                 pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
    1074             :                             }
    1075             :                         }
    1076             :                     }
    1077             : 
    1078           2 :                     break;
    1079             :                 }
    1080             : 
    1081          10 :                 aRg.aStart++;
    1082             :             }
    1083             :         }
    1084           1 :         else if( pDestTxtNd )
    1085             :         {
    1086             :             // Problems with insertion of table selections into "normal" text solved.
    1087             :             // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
    1088             :             // the undo operation will try to merge this node after removing the table.
    1089             :             // If we didn't split a textnode, the PaM should start at the inserted table node
    1090           1 :             if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
    1091             :             {    // Insertion at the last position of a textnode (empty or not)
    1092           1 :                 ++aInsPos; // The table will be inserted behind the text node
    1093             :             }
    1094           0 :             else if( rPos.nContent.GetIndex() )
    1095             :             {   // Insertion in the middle of a text node, it has to be split
    1096             :                 // (and joined from undo)
    1097           0 :                 bStartIsTxtNode = true;
    1098             : 
    1099           0 :                 const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
    1100             :                 {
    1101           0 :                     ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
    1102           0 :                     pDoc->SplitNode( rPos, false );
    1103             :                 }
    1104             : 
    1105           0 :                 if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
    1106             :                 {
    1107             :                     // after the SplitNode, span the CpyPam correctly again
    1108           0 :                     pCopyPam->Move( fnMoveBackward, fnGoCntnt );
    1109           0 :                     pCopyPam->Move( fnMoveBackward, fnGoCntnt );
    1110             :                 }
    1111             : 
    1112             :                 // Correct the area again
    1113           0 :                 if( bEndEqualIns )
    1114           0 :                     aRg.aEnd--;
    1115             :                 // The end would also be moved
    1116           0 :                 else if( rPos == *pEnd )
    1117             :                 {
    1118           0 :                     rPos.nNode-=2;
    1119           0 :                     rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
    1120           0 :                                             nCntntEnd );
    1121           0 :                     rPos.nNode++;
    1122           0 :                     aRg.aEnd--;
    1123             :                 }
    1124             :             }
    1125           0 :             else if( bCanMoveBack )
    1126             :             {   //Insertion at the first position of a text node. It will not be splitted, the table
    1127             :                 // will be inserted before the text node.
    1128             :                 // See below, before the SetInsertRange funciton of the undo object will be called,
    1129             :                 // the CpyPam would be moved to the next content position. This has to be avoided
    1130             :                 // We want to be moved to the table node itself thus we have to set bCanMoveBack
    1131             :                 // and to manipulate pCopyPam.
    1132           0 :                 bCanMoveBack = false;
    1133           0 :                 pCopyPam->GetPoint()->nNode--;
    1134             :             }
    1135             :         }
    1136             : 
    1137         100 :         pDestTxtNd = aInsPos.GetNode().GetTxtNode();
    1138         100 :         if( pEndTxtNd )
    1139             :         {
    1140         100 :             SwIndex aDestIdx( rPos.nContent );
    1141         100 :             if( !pDestTxtNd )
    1142             :             {
    1143           1 :                 pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
    1144           2 :                             pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
    1145           1 :                 aDestIdx.Assign( pDestTxtNd, 0  );
    1146           1 :                 aInsPos--;
    1147             : 
    1148             :                 // if we have to insert an extra text node
    1149             :                 // at the destination, this node will be our new destination
    1150             :                 // (text) node, and thus we set bStartisTxtNode to true. This
    1151             :                 // will ensure that this node will be deleted during Undo
    1152             :                 // using JoinNext.
    1153             :                 OSL_ENSURE( !bStartIsTxtNode, "Oops, undo may be instable now." );
    1154           1 :                 bStartIsTxtNode = true;
    1155             :             }
    1156             : 
    1157             :             // Save numrule at destination
    1158             :             // #i86492# - Safe also <ListId> item of destination.
    1159         100 :             int aNumRuleState = SFX_ITEM_UNKNOWN;
    1160         200 :             SwNumRuleItem aNumRuleItem;
    1161         100 :             int aListIdState = SFX_ITEM_UNKNOWN;
    1162         200 :             SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
    1163             :             {
    1164         100 :                 const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
    1165         100 :                 if (pAttrSet != NULL)
    1166             :                 {
    1167           4 :                     const SfxPoolItem * pItem = NULL;
    1168             : 
    1169             :                     aNumRuleState =
    1170           4 :                         pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
    1171           4 :                     if (SFX_ITEM_SET == aNumRuleState)
    1172           0 :                         aNumRuleItem = *((SwNumRuleItem *) pItem);
    1173             : 
    1174             :                     aListIdState =
    1175           4 :                         pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
    1176           4 :                     if (SFX_ITEM_SET == aListIdState)
    1177           0 :                         aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
    1178             :                 }
    1179             :             }
    1180             : 
    1181         100 :             const bool bEmptyDestNd = pDestTxtNd->GetTxt().isEmpty();
    1182         100 :             pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
    1183         200 :                             pEnd->nContent.GetIndex() );
    1184             : 
    1185             :             // Also copy all format templates
    1186         100 :             if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
    1187             :             {
    1188          95 :                 pEndTxtNd->CopyCollFmt( *pDestTxtNd );
    1189             : 
    1190          95 :                 if ( bOneNode )
    1191             :                 {
    1192             :                     /* If only a part of one paragraph is copied
    1193             :                        restore the numrule at the destination. */
    1194             :                     // #i86492# - restore also <ListId> item
    1195          28 :                     if ( !lcl_MarksWholeNode(rPam) )
    1196             :                     {
    1197           0 :                         if (SFX_ITEM_SET == aNumRuleState)
    1198             :                         {
    1199           0 :                             pDestTxtNd->SetAttr(aNumRuleItem);
    1200             :                         }
    1201             :                         else
    1202             :                         {
    1203           0 :                             pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
    1204             :                         }
    1205           0 :                         if (SFX_ITEM_SET == aListIdState)
    1206             :                         {
    1207           0 :                             pDestTxtNd->SetAttr(aListIdItem);
    1208             :                         }
    1209             :                         else
    1210             :                         {
    1211           0 :                             pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
    1212             :                         }
    1213             :                     }
    1214             :                 }
    1215         100 :             }
    1216             :         }
    1217             : 
    1218         100 :         if( bCopyAll || aRg.aStart != aRg.aEnd )
    1219             :         {
    1220          69 :             SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
    1221          69 :             if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
    1222             :             {
    1223          39 :                 aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
    1224          39 :                 if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, false ) )
    1225           0 :                     pDestTxtNd->ResetAttr( RES_BREAK );
    1226          39 :                 if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, false ) )
    1227           0 :                     pDestTxtNd->ResetAttr( RES_PAGEDESC );
    1228             :             }
    1229             : 
    1230          69 :             if( aInsPos == pEnd->nNode )
    1231             :             {
    1232           0 :                 SwNodeIndex aSaveIdx( aInsPos, -1 );
    1233           0 :                 CopyWithFlyInFly( aRg, 0,aInsPos, &rPam, bMakeNewFrms, sal_False );
    1234           0 :                 ++aSaveIdx;
    1235           0 :                 pEnd->nNode = aSaveIdx;
    1236           0 :                 pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
    1237             :             }
    1238             :             else
    1239          69 :                 CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam, bMakeNewFrms, sal_False );
    1240             : 
    1241          69 :             bCopyBookmarks = false;
    1242             : 
    1243             :             // Put the breaks back into the first node
    1244          69 :             if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
    1245           0 :                     pCopyPam->GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode()))
    1246             :             {
    1247           0 :                 pDestTxtNd->SetAttr( aBrkSet );
    1248          69 :             }
    1249             :         }
    1250             :     } while( false );
    1251             : 
    1252             :     // Adjust position (in case it was moved / in another node)
    1253         102 :     rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
    1254         204 :                             rPos.nContent.GetIndex() );
    1255             : 
    1256         102 :     if( rPos.nNode != aInsPos )
    1257             :     {
    1258           1 :         pCopyPam->GetMark()->nNode = aInsPos;
    1259           1 :         pCopyPam->GetMark()->nContent.Assign(pCopyPam->GetCntntNode(false), 0);
    1260           1 :         rPos = *pCopyPam->GetMark();
    1261             :     }
    1262             :     else
    1263         101 :         *pCopyPam->GetMark() = rPos;
    1264             : 
    1265         102 :     if ( !bAfterTable )
    1266         102 :         pCopyPam->Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
    1267             :     else
    1268             :     {
    1269             :         // Reset the offset to 0 as it was before the insertion
    1270           0 :         pCopyPam->GetPoint()->nContent -= pCopyPam->GetPoint()->nContent;
    1271             : 
    1272           0 :         pCopyPam->GetPoint()->nNode++;
    1273             :         // If the next node is a start node, then step back: the start node
    1274             :         // has been copied and needs to be in the selection for the undo
    1275           0 :         if (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode())
    1276           0 :             pCopyPam->GetPoint()->nNode--;
    1277             : 
    1278             :     }
    1279         102 :     pCopyPam->Exchange();
    1280             : 
    1281             :     // Also copy all bookmarks
    1282         102 :     if( bCopyBookmarks && getIDocumentMarkAccess()->getAllMarksCount() )
    1283          26 :         lcl_CopyBookmarks( rPam, *pCopyPam );
    1284             : 
    1285         102 :     if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
    1286             :     {
    1287             :         assert(*pCopyPam->GetPoint() == rPos);
    1288             :         // the Node rPos points to may be deleted so unregister ...
    1289           2 :         rPos.nContent = SwIndex(0);
    1290           2 :         lcl_DeleteRedlines(rPam, *pCopyPam);
    1291           2 :         rPos = *pCopyPam->GetPoint(); // ... and restore.
    1292             :     }
    1293             : 
    1294             :     // If Undo is enabled, store the inserted area
    1295         102 :     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
    1296             :     {
    1297           4 :         pUndo->SetInsertRange( *pCopyPam, true, bStartIsTxtNode );
    1298             :     }
    1299             : 
    1300         102 :     if( pCpyRange )
    1301             :     {
    1302           5 :         pCpyRange->SetMark();
    1303           5 :         *pCpyRange->GetPoint() = *pCopyPam->GetPoint();
    1304           5 :         *pCpyRange->GetMark() = *pCopyPam->GetMark();
    1305             :     }
    1306             : 
    1307         102 :     if ( pNumRuleToPropagate != NULL )
    1308             :     {
    1309             :         // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
    1310           0 :         pDoc->SetNumRule( *pCopyPam, *pNumRuleToPropagate, false,
    1311           0 :                           aListIdToPropagate, true, true );
    1312             :     }
    1313             : 
    1314         102 :     pDoc->SetRedlineMode_intern( eOld );
    1315         102 :     pDoc->SetModified();
    1316             : 
    1317         204 :     return true;
    1318             : }
    1319             : 
    1320             : // Copy method from SwDoc - "copy Flys in Flys"
    1321         289 : void SwDoc::CopyWithFlyInFly(
    1322             :     const SwNodeRange& rRg,
    1323             :     const sal_Int32 nEndContentIndex,
    1324             :     const SwNodeIndex& rInsPos,
    1325             :     const SwPaM* pCopiedPaM,
    1326             :     const sal_Bool bMakeNewFrms,
    1327             :     const sal_Bool bDelRedlines,
    1328             :     const sal_Bool bCopyFlyAtFly ) const
    1329             : {
    1330         289 :     SwDoc* pDest = rInsPos.GetNode().GetDoc();
    1331             : 
    1332         289 :     _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
    1333             : 
    1334         578 :     SwNodeIndex aSavePos( rInsPos, -1 );
    1335         289 :     bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
    1336         289 :     GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
    1337         289 :     ++aSavePos;
    1338         289 :     if( bEndIsEqualEndPos )
    1339           0 :         ((SwNodeIndex&)rRg.aEnd) = aSavePos;
    1340             : 
    1341         289 :     aRedlRest.Restore();
    1342             : 
    1343             : #if OSL_DEBUG_LEVEL > 0
    1344             :     {
    1345             :         //JP 17.06.99: Bug 66973 - check count only if the selection is in
    1346             :         // the same section or there's no section, because sections that are
    1347             :         // not fully selected are not copied.
    1348             :         const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
    1349             :         SwNodeIndex aTmpI( rRg.aEnd, -1 );
    1350             :         const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
    1351             :         if( pSSectNd == pESectNd &&
    1352             :             !rRg.aStart.GetNode().IsSectionNode() &&
    1353             :             !aTmpI.GetNode().IsEndNode() )
    1354             :         {
    1355             :             OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
    1356             :                     rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
    1357             :                     "An insufficient number of nodes were copied!" );
    1358             :         }
    1359             :     }
    1360             : #endif
    1361             : 
    1362             :     {
    1363         289 :         ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
    1364         289 :         CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
    1365             :     }
    1366             : 
    1367         578 :     SwNodeRange aCpyRange( aSavePos, rInsPos );
    1368             : 
    1369             :     // Also copy all bookmarks
    1370         289 :     if( getIDocumentMarkAccess()->getAllMarksCount() )
    1371             :     {
    1372         184 :         SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
    1373         368 :         SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
    1374             : 
    1375             :         lcl_CopyBookmarks(
    1376             :             pCopiedPaM != NULL ? *pCopiedPaM : aRgTmp,
    1377         368 :             aCpyTmp );
    1378             :     }
    1379             : 
    1380         289 :     if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
    1381           0 :         lcl_DeleteRedlines( rRg, aCpyRange );
    1382             : 
    1383         578 :     pDest->GetNodes()._DelDummyNodes( aCpyRange );
    1384         289 : }
    1385             : 
    1386           0 : static void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
    1387             : {
    1388           0 :     SwFmtChain aSrc( pSrc->GetChain() );
    1389           0 :     if ( !aSrc.GetNext() )
    1390             :     {
    1391           0 :         aSrc.SetNext( pDest );
    1392           0 :         pSrc->SetFmtAttr( aSrc );
    1393             :     }
    1394           0 :     SwFmtChain aDest( pDest->GetChain() );
    1395           0 :     if ( !aDest.GetPrev() )
    1396             :     {
    1397           0 :         aDest.SetPrev( pSrc );
    1398           0 :         pDest->SetFmtAttr( aDest );
    1399           0 :     }
    1400           0 : }
    1401             : 
    1402        2204 : void SwDoc::CopyFlyInFlyImpl(
    1403             :     const SwNodeRange& rRg,
    1404             :     const sal_Int32 nEndContentIndex,
    1405             :     const SwNodeIndex& rStartIdx,
    1406             :     const bool bCopyFlyAtFly ) const
    1407             : {
    1408             :     // First collect all Flys, sort them according to their ordering number,
    1409             :     // and then only copy them. This maintains the ordering numbers (which are only
    1410             :     // managed in the DrawModel).
    1411        2204 :     SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
    1412        2204 :     ::std::set< _ZSortFly > aSet;
    1413        2204 :     sal_uInt16 nArrLen = GetSpzFrmFmts()->size();
    1414             : 
    1415       18104 :     for ( sal_uInt16 n = 0; n < nArrLen; ++n )
    1416             :     {
    1417       15900 :         SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
    1418       15900 :         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
    1419       15900 :         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
    1420       15900 :         bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
    1421       31656 :         if ( pAPos &&
    1422        3480 :              ( bAtCntnt ||
    1423        6960 :               (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
    1424        3480 :               (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
    1425        8978 :              (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
    1426           0 :                     ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
    1427       12542 :                     : ( IsRedlineMove()
    1428         487 :                             ? rRg.aStart < pAPos->nNode
    1429       49585 :                             : rRg.aStart <= pAPos->nNode )) &&
    1430        8114 :              pAPos->nNode <= rRg.aEnd )
    1431             :         {
    1432             :             //frames at the last source node are not always copied:
    1433             :             //- if the node is empty and is the last node of the document or a table cell
    1434             :             //  or a text frame then tey have to be copied
    1435             :             //- if the content index in this node is > 0 then paragph and frame bound objects are copied
    1436             :             //- to-character bound objects are copied if their index is <= nEndContentIndex
    1437         171 :             bool bAdd = false;
    1438         171 :             if( pAPos->nNode < rRg.aEnd )
    1439         171 :                 bAdd = true;
    1440         171 :             if (!bAdd && !IsRedlineMove()) // fdo#40599: not for redline move
    1441             :             {
    1442           0 :                 bool bEmptyNode = false;
    1443           0 :                 bool bLastNode = false;
    1444             :                 // is the node empty?
    1445           0 :                 const SwNodes& rNodes = pAPos->nNode.GetNodes();
    1446             :                 SwTxtNode* pTxtNode;
    1447           0 :                 if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
    1448             :                 {
    1449           0 :                     bEmptyNode = pTxtNode->GetTxt().isEmpty();
    1450           0 :                     if( bEmptyNode )
    1451             :                     {
    1452             :                         //last node information is only necessary to know for the last TextNode
    1453           0 :                         SwNodeIndex aTmp( pAPos->nNode );
    1454           0 :                         ++aTmp;//goto next node
    1455           0 :                         while (aTmp.GetNode().IsEndNode())
    1456             :                         {
    1457           0 :                             if( aTmp == rNodes.GetEndOfContent().GetIndex() )
    1458             :                             {
    1459           0 :                                 bLastNode = true;
    1460           0 :                                 break;
    1461             :                             }
    1462           0 :                             ++aTmp;
    1463           0 :                         }
    1464             :                     }
    1465             :                 }
    1466           0 :                 bAdd = bLastNode && bEmptyNode;
    1467           0 :                 if( !bAdd )
    1468             :                 {
    1469           0 :                     if( bAtCntnt )
    1470           0 :                         bAdd = nEndContentIndex > 0;
    1471             :                     else
    1472           0 :                         bAdd = pAPos->nContent <= nEndContentIndex;
    1473             :                 }
    1474             :             }
    1475         171 :             if( bAdd )
    1476         171 :                 aSet.insert( _ZSortFly( pFmt, pAnchor, nArrLen + aSet.size() ));
    1477             :         }
    1478             :     }
    1479             : 
    1480             :     // Store all copied (and also the newly created) frames in another array.
    1481             :     // They are stored as matching the originals, so that we will be later
    1482             :     // able to build the chains accordingly.
    1483        4408 :     ::std::vector< SwFrmFmt* > aVecSwFrmFmt;
    1484        2204 :     ::std::set< _ZSortFly >::const_iterator it=aSet.begin();
    1485             : 
    1486        4579 :     while (it != aSet.end())
    1487             :     {
    1488             :         // #i59964#
    1489             :         // correct determination of new anchor position
    1490         171 :         SwFmtAnchor aAnchor( *(*it).GetAnchor() );
    1491         171 :         SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
    1492             :         // for at-paragraph and at-character anchored objects the new anchor
    1493             :         // position can *not* be determined by the difference of the current
    1494             :         // anchor position to the start of the copied range, because not
    1495             :         // complete selected sections in the copied range aren't copied - see
    1496             :         // method <SwNodes::_CopyNodes(..)>.
    1497             :         // Thus, the new anchor position in the destination document is found
    1498             :         // by counting the text nodes.
    1499         209 :         if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
    1500          38 :             (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
    1501             :         {
    1502             :             // First, determine number of anchor text node in the copied range.
    1503             :             // Note: The anchor text node *have* to be inside the copied range.
    1504         171 :             sal_uLong nAnchorTxtNdNumInRange( 0L );
    1505         171 :             bool bAnchorTxtNdFound( false );
    1506         171 :             SwNodeIndex aIdx( rRg.aStart );
    1507         890 :             while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
    1508             :             {
    1509         548 :                 if ( aIdx.GetNode().IsTxtNode() )
    1510             :                 {
    1511         229 :                     ++nAnchorTxtNdNumInRange;
    1512         229 :                     bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
    1513             :                 }
    1514             : 
    1515         548 :                 ++aIdx;
    1516             :             }
    1517         171 :             if ( !bAnchorTxtNdFound )
    1518             :             {
    1519             :                 // This case can *not* happen, but to be robust take the first
    1520             :                 // text node in the destination document.
    1521             :                 OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
    1522           0 :                 nAnchorTxtNdNumInRange = 1;
    1523             :             }
    1524             :             // Second, search corresponding text node in destination document
    1525             :             // by counting forward from start insert position <rStartIdx> the
    1526             :             // determined number of text nodes.
    1527         171 :             aIdx = rStartIdx;
    1528         342 :             SwNodeIndex aAnchorNdIdx( rStartIdx );
    1529             :             const SwNode& aEndOfContentNd =
    1530         171 :                                     aIdx.GetNode().GetNodes().GetEndOfContent();
    1531        1438 :             while ( nAnchorTxtNdNumInRange > 0 &&
    1532         548 :                     &(aIdx.GetNode()) != &aEndOfContentNd )
    1533             :             {
    1534         548 :                 if ( aIdx.GetNode().IsTxtNode() )
    1535             :                 {
    1536         229 :                     --nAnchorTxtNdNumInRange;
    1537         229 :                     aAnchorNdIdx = aIdx;
    1538             :                 }
    1539             : 
    1540         548 :                 ++aIdx;
    1541             :             }
    1542         171 :             if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
    1543             :             {
    1544             :                 // This case can *not* happen, but to be robust take the first
    1545             :                 // text node in the destination document.
    1546             :                 OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
    1547           0 :                 aAnchorNdIdx = rStartIdx;
    1548           0 :                 while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
    1549             :                 {
    1550           0 :                     ++aAnchorNdIdx;
    1551             :                 }
    1552             :             }
    1553             :             // apply found anchor text node as new anchor position
    1554         342 :             pNewPos->nNode = aAnchorNdIdx;
    1555             :         }
    1556             :         else
    1557             :         {
    1558           0 :             long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
    1559           0 :             SwNodeIndex aIdx( rStartIdx, nOffset );
    1560           0 :             pNewPos->nNode = aIdx;
    1561             :         }
    1562             :         // Set the character bound Flys back at the original character
    1563         209 :         if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
    1564          38 :              pNewPos->nNode.GetNode().IsTxtNode() )
    1565             :         {
    1566          38 :             pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
    1567          76 :                                         pNewPos->nContent.GetIndex() );
    1568             :         }
    1569             :         else
    1570             :         {
    1571         133 :             pNewPos->nContent.Assign( 0, 0 );
    1572             :         }
    1573             : 
    1574             :         // Check recursion: copy content in its own frame, then don't copy it.
    1575         171 :         bool bMakeCpy = true;
    1576         171 :         if( pDest == this )
    1577             :         {
    1578         171 :             const SwFmtCntnt& rCntnt = (*it).GetFmt()->GetCntnt();
    1579             :             const SwStartNode* pSNd;
    1580         477 :             if( rCntnt.GetCntntIdx() &&
    1581         270 :                 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
    1582         441 :                 pSNd->GetIndex() < rStartIdx.GetIndex() &&
    1583         135 :                 rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
    1584             :             {
    1585           0 :                 bMakeCpy = false;
    1586           0 :                 aSet.erase (it++);
    1587           0 :                 continue;
    1588             :             }
    1589             :         }
    1590             : 
    1591             :         // Copy the format and set the new anchor
    1592         171 :         if( bMakeCpy )
    1593         171 :             aVecSwFrmFmt.push_back( pDest->CopyLayoutFmt( *(*it).GetFmt(),
    1594         342 :                         aAnchor, false, true ) );
    1595         171 :         ++it;
    1596         171 :     }
    1597             : 
    1598             :     // Rebuild as much as possible of all chains that are available in the original,
    1599             :     OSL_ENSURE( aSet.size() == aVecSwFrmFmt.size(), "Missing new Flys" );
    1600        2204 :     if ( aSet.size() == aVecSwFrmFmt.size() )
    1601             :     {
    1602        2204 :         size_t n = 0;
    1603        2375 :         for (::std::set< _ZSortFly >::const_iterator nIt=aSet.begin() ; nIt != aSet.end(); ++nIt, ++n )
    1604             :         {
    1605         171 :             const SwFrmFmt *pFmtN = (*nIt).GetFmt();
    1606         171 :             const SwFmtChain &rChain = pFmtN->GetChain();
    1607         171 :             int nCnt = int(0 != rChain.GetPrev());
    1608         171 :             nCnt += rChain.GetNext() ? 1: 0;
    1609         171 :             size_t k = 0;
    1610        3954 :             for (::std::set< _ZSortFly >::const_iterator kIt=aSet.begin() ; kIt != aSet.end(); ++kIt, ++k )
    1611             :             {
    1612        3783 :                 const SwFrmFmt *pFmtK = (*kIt).GetFmt();
    1613        3783 :                 if ( rChain.GetPrev() == pFmtK )
    1614             :                 {
    1615           0 :                     ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]),
    1616           0 :                                      static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]) );
    1617           0 :                     --nCnt;
    1618             :                 }
    1619        3783 :                 else if ( rChain.GetNext() == pFmtK )
    1620             :                 {
    1621           0 :                     ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]),
    1622           0 :                                      static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]) );
    1623           0 :                     --nCnt;
    1624             :                 }
    1625             :             }
    1626             :         }
    1627        2204 :     }
    1628        2204 : }
    1629             : 
    1630             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10