LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/docnode - ndcopy.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 435 779 55.8 %
Date: 2012-12-27 Functions: 17 21 81.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10