[Libreoffice-commits] core.git: Branch 'private/jmux/layout-fixes' - 38 commits - comphelper/source connectivity/source include/sfx2 include/svl include/tools sc/inc sc/Library_sc.mk sc/qa sc/source sfx2/source svl/source sw/inc sw/qa sw/source writerfilter/Library_writerfilter.mk

Jan-Marek Glogowski glogow at fbihome.de
Mon Jul 14 04:12:18 PDT 2014


Rebased ref, commits from common ancestor:
commit eb6fb17d38d01849b2b15896df4761dcd7eb5587
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sun Jul 13 20:18:56 2014 +0200

    Refactor a tiny bit of SwLayAction::IsShortCut
    
    Change-Id: I13d4fbebec02bddaa27e8929188d497dde715730

diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index 023f64f..0fcbf8d 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1173,15 +1173,13 @@ bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
                 }
                 // #121980# - no shortcut, if at previous page
                 // an anchored object is registered, whose anchor is <pCntnt>.
-                else if ( prPage->GetPrev() &&
-                          static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
+                else if ( prPage->GetPrev() )
                 {
                     SwSortedObjs* pObjs =
                         static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
                     if ( pObjs )
                     {
-                        sal_uInt32 i = 0;
-                        for ( ; i < pObjs->Count(); ++i )
+                        for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
                         {
                             SwAnchoredObject* pObj = (*pObjs)[i];
                             if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
commit 21b84ff3b6e8a053fe20e4a48a883b20cdd6118c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sun Jul 13 20:15:55 2014 +0200

    fdo#80926 Don't move anchors of invalid pages
    
    If the anchor is valid, check if its page is valid too,
    before moving anchors on view change.
    
    Change-Id: Idffdfdb786cb29a105c06d652e6ad7315abfb4c5

diff --git a/sw/source/core/view/vdraw.cxx b/sw/source/core/view/vdraw.cxx
index db32944..143169f 100644
--- a/sw/source/core/view/vdraw.cxx
+++ b/sw/source/core/view/vdraw.cxx
@@ -228,6 +228,17 @@ void SwViewImp::NotifySizeChg( const Size &rNewSz )
             {
                 continue;
             }
+            else
+            {
+                // Actually this should never happen but currently layouting
+                // is broken. So don't move anchors, if the page is invalid.
+                // This should be turned into an DBG_ASSERT, once layouting is fixed!
+                const SwPageFrm *pPageFrm = pAnchor->FindPageFrm();
+                if (!pPageFrm || pPageFrm->IsInvalid() ) {
+                    SAL_WARN( "sw.resizeview", "Trying to move anchor from invalid page - fix layouting!" );
+                    continue;
+                }
+            }
 
             // no move for drawing objects in header/footer
             if ( pAnchor->FindFooterOrHeader() )
commit 1b0982ed41d28ad3c01d1b92b2aece22a60038e2
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jul 12 23:17:31 2014 +0200

    fdo#70346 MM: hide sections based on field values
    
    This recalculates the section conditions based on the mail merge
    fields before converting the fields to text.
    
    It also removes the condition from the sections, as the fields
    won't be available in the merged document.
    
    Change-Id: I82a5f9f6962628a76c836e8e2a7c9e264fdc16e0

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 0601873..77a78a2 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -127,6 +127,7 @@
 #include <rootfrm.hxx>
 #include <fmtpdsc.hxx>
 #include <ndtxt.hxx>
+#include <calc.hxx>
 
 #include <boost/scoped_ptr.hpp>
 
@@ -808,6 +809,27 @@ static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
     rWorkShell.SetLabelDoc( false );
 }
 
+static void lcl_HideConditionalSections( SwDoc *rDoc, SwWrtShell &rWorkShell )
+{
+    sal_uInt16 nSections = rWorkShell.GetSectionFmtCount();
+    for( sal_uInt16 nSection = 0; nSection < nSections; ++nSection )
+    {
+        const SwSectionFmt& aSectFmt = rWorkShell.GetSectionFmt( nSection );
+        SwSection *aSect = aSectFmt.GetSection();
+        if ( aSect->IsHidden() && !aSect->GetCondition().isEmpty() )
+        {
+            SwCalc aCalc( *rDoc );
+            rDoc->FldsToCalc( aCalc, aSectFmt.GetSectionNode()->GetIndex(), USHRT_MAX );
+            bool bRecalcCondHidden =
+                    aCalc.Calculate( aSect->GetCondition() ).GetBool();
+
+            // Fields will be removed, so empty the condition
+            aSect->SetCondition( OUString() );
+            aSect->SetCondHidden( bRecalcCondHidden );
+        }
+    }
+}
+
 #ifdef DBG_UTIL
 
 #define MAX_DOC_DUMP 3
@@ -1068,6 +1090,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 //                            pWorkDoc->UpdateFlds(NULL, false);
                             rWorkShell.SwViewShell::UpdateFlds();
                             SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh));
+                            lcl_HideConditionalSections( pWorkDoc, rWorkShell );
 
                             pWorkDoc->RemoveInvisibleContent();
 
@@ -2838,6 +2861,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
             rWorkShell.SwViewShell::UpdateFlds();
             SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
+            lcl_HideConditionalSections( pWorkDoc, rWorkShell );
 
             // strip invisible content and convert fields to text
             rWorkShell.RemoveInvisibleContent();
commit 18d9eb1c2008eb41327f8dc431eb56fc333b4fea
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jul 12 19:27:11 2014 +0200

    Invalidate rect cache before moving object
    
    Otherwise I get sw/source/core/layout/anchoredobject.cxx:582:
    
      <SwAnchoredObject::GetObjRectWithSpaces> - cache for object
      rectangle inclusive spaces marked as valid, but it couldn't be.
      Missing invalidation of cache. Please inform OD.
    
    Change-Id: I3f315b15fca6e2480c11183269be5583e6aea123

diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
index 09451a5..78ae607 100644
--- a/sw/source/core/layout/anchoreddrawobject.cxx
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -793,14 +793,20 @@ void SwAnchoredDrawObject::_SetPositioningAttr()
 
         // --> #i71182#
         // only change position - do not lose other attributes
+
         SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
-        aHori.SetPos( nHoriPos );
-        GetFrmFmt().SetFmtAttr( aHori );
+        if (nHoriPos != aHori.GetPos()) {
+            aHori.SetPos( nHoriPos );
+            InvalidateObjRectWithSpaces();
+            GetFrmFmt().SetFmtAttr( aHori );
+        }
 
         SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
-
-        aVert.SetPos( nVertPos );
-        GetFrmFmt().SetFmtAttr( aVert );
+        if (nVertPos != aVert.GetPos()) {
+            aVert.SetPos( nVertPos );
+            InvalidateObjRectWithSpaces();
+            GetFrmFmt().SetFmtAttr( aVert );
+        }
 
         // --> #i36010# - set layout direction of the position
         GetFrmFmt().SetPositionLayoutDir(
commit ab6d468bedc1e4c07fb9db3bf9a65afcbdf5efcf
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jul 12 13:35:54 2014 +0200

    Fix moving out-of-bounds draw / fly objects
    
    Actually move the object in the right direction, if it's outside
    of the document boundaries.
    
    Fixes the mysterious effect, that negative y-offset in fdo#80926
    changed the objects x-offset values.
    
    Change-Id: If88cf2a07fb44537b2e047e77c5e009664db94af

diff --git a/sw/source/core/view/vdraw.cxx b/sw/source/core/view/vdraw.cxx
index cee96ce..db32944 100644
--- a/sw/source/core/view/vdraw.cxx
+++ b/sw/source/core/view/vdraw.cxx
@@ -248,10 +248,10 @@ void SwViewImp::NotifySizeChg( const Size &rNewSz )
 
                 // Don't let large objects dissappear to the top
                 aSz.Width() = aSz.Height() = 0;
-                if ( aObjBound.Bottom() < aDocRect.Top() )
-                    aSz.Width() = (aObjBound.Bottom() - aDocRect.Top()) - MINFLY;
                 if ( aObjBound.Right() < aDocRect.Left() )
-                    aSz.Height() = (aObjBound.Right() - aDocRect.Left()) - MINFLY;
+                    aSz.Width() = (aDocRect.Left() - aObjBound.Right()) + MINFLY;
+                if ( aObjBound.Bottom() < aDocRect.Top() )
+                    aSz.Height() = (aDocRect.Top() - aObjBound.Bottom()) + MINFLY;
                 if ( aSz.Width() || aSz.Height() )
                     pObj->Move( aSz );
             }
commit ce4b086ca2ea0ac98883056f9c58075c921ee47b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jul 12 13:34:01 2014 +0200

    Better variable naming in SwViewImp::NotifySizeChg
    
    Make it obvious, which variable contains the document boundaries and
    which the draw / fly object boundaries.
    
    Change-Id: I0bc2bcb5515e317c7a204b3458b92c61482e1a5c

diff --git a/sw/source/core/view/vdraw.cxx b/sw/source/core/view/vdraw.cxx
index e8a8bdb..cee96ce 100644
--- a/sw/source/core/view/vdraw.cxx
+++ b/sw/source/core/view/vdraw.cxx
@@ -193,14 +193,14 @@ void SwViewImp::NotifySizeChg( const Size &rNewSz )
         GetPageView()->GetPage()->SetSize( rNewSz );
 
     // Limitation of the work area
-    const Rectangle aRect( Point( DOCUMENTBORDER, DOCUMENTBORDER ), rNewSz );
+    const Rectangle aDocRect( Point( DOCUMENTBORDER, DOCUMENTBORDER ), rNewSz );
     const Rectangle &rOldWork = GetDrawView()->GetWorkArea();
     bool bCheckDrawObjs = false;
-    if ( aRect != rOldWork )
+    if ( aDocRect != rOldWork )
     {
-        if ( rOldWork.Bottom() > aRect.Bottom() || rOldWork.Right() > aRect.Right())
+        if ( rOldWork.Bottom() > aDocRect.Bottom() || rOldWork.Right() > aDocRect.Right())
             bCheckDrawObjs = true;
-        GetDrawView()->SetWorkArea( aRect );
+        GetDrawView()->SetWorkArea( aDocRect );
     }
     if ( !bCheckDrawObjs )
         return;
@@ -235,23 +235,23 @@ void SwViewImp::NotifySizeChg( const Size &rNewSz )
                 continue;
             }
 
-            const Rectangle aBound( pObj->GetCurrentBoundRect() );
-            if ( !aRect.IsInside( aBound ) )
+            const Rectangle aObjBound( pObj->GetCurrentBoundRect() );
+            if ( !aDocRect.IsInside( aObjBound ) )
             {
                 Size aSz;
-                if ( aBound.Left() > aRect.Right() )
-                    aSz.Width() = (aRect.Right() - aBound.Left()) - MINFLY;
-                if ( aBound.Top() > aRect.Bottom() )
-                    aSz.Height() = (aRect.Bottom() - aBound.Top()) - MINFLY;
+                if ( aObjBound.Left() > aDocRect.Right() )
+                    aSz.Width() = (aDocRect.Right() - aObjBound.Left()) - MINFLY;
+                if ( aObjBound.Top() > aDocRect.Bottom() )
+                    aSz.Height() = (aDocRect.Bottom() - aObjBound.Top()) - MINFLY;
                 if ( aSz.Width() || aSz.Height() )
                     pObj->Move( aSz );
 
                 // Don't let large objects dissappear to the top
                 aSz.Width() = aSz.Height() = 0;
-                if ( aBound.Bottom() < aRect.Top() )
-                    aSz.Width() = (aBound.Bottom() - aRect.Top()) - MINFLY;
-                if ( aBound.Right() < aRect.Left() )
-                    aSz.Height() = (aBound.Right() - aRect.Left()) - MINFLY;
+                if ( aObjBound.Bottom() < aDocRect.Top() )
+                    aSz.Width() = (aObjBound.Bottom() - aDocRect.Top()) - MINFLY;
+                if ( aObjBound.Right() < aDocRect.Left() )
+                    aSz.Height() = (aObjBound.Right() - aDocRect.Left()) - MINFLY;
                 if ( aSz.Width() || aSz.Height() )
                     pObj->Move( aSz );
             }
commit fa292eceb5a047f48daa97a0bef575c24e1be594
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Jul 2 11:17:17 2014 +0200

    Fixes multiple-page-anchored-draws.odt
    
    Change-Id: I5ad726da647df8621bc0a16caa78a28b7d2d01c1

diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index bc8e403..d4f40c2 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -1221,6 +1221,9 @@ else
             }
         }
 
+        if ( pTargetShell )
+            pTargetShell->CalcLayout();
+
         // finally copy page bound frames
         const SwFrmFmts *pSpzFrmFmts = rSource.GetSpzFrmFmts();
         for ( sal_uInt16 i = 0; i < pSpzFrmFmts->size(); ++i )
commit 73ba7988d63eaef90b411cdd09c269a8396ddfb3
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 15:45:47 2014 +0200

    Fix single node CopyRange
    
    Change-Id: Iadf21d3928303c2ab8df0d93dabd969ed1ff7e09

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index d0e31aa..b276d4d 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -469,7 +469,8 @@ private:
     void CopyFlyInFlyImpl(  const SwNodeRange& rRg,
                             const sal_Int32 nEndContentIndex,
                             const SwNodeIndex& rStartIdx,
-                            const bool bCopyFlyAtFly = false ) const;
+                            const bool bCopyFlyAtFly = false,
+                            const bool bMergedFirstNode = false ) const;
     sal_Int8 SetFlyFrmAnchor( SwFrmFmt& rFlyFmt, SfxItemSet& rSet, bool bNewFrms );
 
     typedef SwFmt* (SwDoc:: *FNCopyFmt)( const OUString&, SwFmt*, bool, bool );
@@ -902,7 +903,8 @@ public:
                             const SwPaM* pCopiedPaM = NULL,
                             bool bMakeNewFrms = true,
                             bool bDelRedlines = true,
-                            bool bCopyFlyAtFly = false ) const;
+                            bool bCopyFlyAtFly = false,
+                            bool bSkipFirstNode = false ) const;
 
     //UUUU Helper that checks for unique items for DrawingLayer items of type NameOrIndex
     // and evtl. corrects that items to ensure unique names for that type. This call may
diff --git a/sw/source/core/docnode/ndcopy.cxx b/sw/source/core/docnode/ndcopy.cxx
index 5443c9f..771e9d7 100644
--- a/sw/source/core/docnode/ndcopy.cxx
+++ b/sw/source/core/docnode/ndcopy.cxx
@@ -673,7 +673,7 @@ SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
     bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
 
     // Catch if there's no copy to do
-    if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
+    if( !rPam.HasMark() || ( *pStt > *pEnd && !bColumnSel ) )
         return false;
 
     // Prevent copying in Flys that are anchored in the area
@@ -923,7 +923,7 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
     SwPosition* pEnd = rPam.End();
 
     // Catch when there's no copy to do.
-    if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
+    if( !rPam.HasMark() || ( *pStt > *pEnd && !bColumnSel ) ||
         //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
         //JP 15.11.2001: don't test inclusive the end, ever exclusive
         ( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
@@ -1011,6 +1011,8 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
         pNumRuleToPropagate = 0;
     }
 
+    bool bHandledStartNode = false;
+
     // This do/while block is only there so that we can break out of it!
     do {
         if( pSttTxtNd )
@@ -1018,6 +1020,8 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
             // Don't copy the beginning completely?
             if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
             {
+                bHandledStartNode = true;
+
                 SwIndex aDestIdx( rPos.nContent );
                 bool bCopyOk = false;
                 if( !pDestTxtNd )
@@ -1093,18 +1097,11 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
                         pEnd->nContent -= nCpyLen;
                 }
 
-                if( bOneNode )
+                if( bCopyCollFmt && bOneNode )
                 {
-                    if( bCopyCollFmt )
-                    {
-                        pSttTxtNd->CopyCollFmt( *pDestTxtNd );
-                        POP_NUMRULE_STATE
-                    }
-
-                    break;
+                    pSttTxtNd->CopyCollFmt( *pDestTxtNd );
+                    POP_NUMRULE_STATE
                 }
-
-                aRg.aStart++;
             }
         }
         else if( pDestTxtNd )
@@ -1161,7 +1158,7 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
         }
 
         pDestTxtNd = aInsPos.GetNode().GetTxtNode();
-        if( pEndTxtNd )
+        if( pEndTxtNd && (!bOneNode || !bHandledStartNode) )
         {
             SwIndex aDestIdx( rPos.nContent );
             if( !pDestTxtNd )
@@ -1205,7 +1202,7 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
         if( bCopyAll || aRg.aStart != aRg.aEnd )
         {
             SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
-            if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
+            if( !bOneNode && pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
             {
                 aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
                 if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, false ) )
@@ -1217,13 +1214,15 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
             if( aInsPos == pEnd->nNode )
             {
                 SwNodeIndex aSaveIdx( aInsPos, -1 );
-                CopyWithFlyInFly( aRg, 0,aInsPos, &rPam, bMakeNewFrms, false );
+                CopyWithFlyInFly( aRg, 0, aInsPos, &rPam, bMakeNewFrms,
+                                  false, false, bHandledStartNode );
                 ++aSaveIdx;
                 pEnd->nNode = aSaveIdx;
                 pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
             }
             else
-                CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam, bMakeNewFrms, false );
+                CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam,
+                                  bMakeNewFrms, false, false, bHandledStartNode );
 
             bCopyBookmarks = false;
 
@@ -1312,7 +1311,8 @@ void SwDoc::CopyWithFlyInFly(
     const SwPaM* pCopiedPaM,
     const bool bMakeNewFrms,
     const bool bDelRedlines,
-    const bool bCopyFlyAtFly ) const
+    const bool bCopyFlyAtFly,
+    const bool bMergedFirstNode ) const
 {
     SwDoc* pDest = rInsPos.GetNode().GetDoc();
 
@@ -1320,13 +1320,17 @@ void SwDoc::CopyWithFlyInFly(
 
     SwNodeIndex aSavePos( rInsPos, -1 );
     bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
-    GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, true );
-    ++aSavePos;
-    if( bEndIsEqualEndPos )
+    SwNodeRange aRg( rRg );
+    if ( bMergedFirstNode )
+        aRg.aStart++;
+    if ( aRg.aStart <= aRg.aEnd )
+        GetNodes()._CopyNodes( aRg, rInsPos, bMakeNewFrms, true );
+    if ( !bMergedFirstNode )
+        ++aSavePos;
+    if ( bEndIsEqualEndPos )
         ((SwNodeIndex&)rRg.aEnd) = aSavePos;
 
     aRedlRest.Restore();
-
 #if OSL_DEBUG_LEVEL > 0
     {
         //JP 17.06.99: Bug 66973 - check count only if the selection is in
@@ -1340,9 +1344,9 @@ void SwDoc::CopyWithFlyInFly(
             !aTmpI.GetNode().IsEndNode() )
         {
             // If the range starts with a SwStartNode, it isn't copied
-            sal_uInt16 offset = (rRg.aStart.GetNode().GetNodeType() != ND_STARTNODE) ? 1 : 0;
+            sal_uInt16 offset = (aRg.aStart.GetNode().GetNodeType() != ND_STARTNODE) ? 1 : 0;
             OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
-                    rRg.aEnd.GetIndex() - rRg.aStart.GetIndex() - 1 + offset,
+                    aRg.aEnd.GetIndex() - aRg.aStart.GetIndex() - 1 + offset,
                     "An insufficient number of nodes were copied!" );
         }
     }
@@ -1350,7 +1354,7 @@ void SwDoc::CopyWithFlyInFly(
 
     {
         ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
-        CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
+        CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly, bMergedFirstNode );
     }
 
     SwNodeRange aCpyRange( aSavePos, rInsPos );
@@ -1392,7 +1396,8 @@ void SwDoc::CopyFlyInFlyImpl(
     const SwNodeRange& rRg,
     const sal_Int32 nEndContentIndex,
     const SwNodeIndex& rStartIdx,
-    const bool bCopyFlyAtFly ) const
+    const bool bCopyFlyAtFly,
+    const bool bMergedFirstNode ) const
 {
     // First collect all Flys, sort them according to their ordering number,
     // and then only copy them. This maintains the ordering numbers (which are only
@@ -1512,6 +1517,9 @@ void SwDoc::CopyFlyInFlyImpl(
 
                 ++aIdx;
             }
+            if ( bMergedFirstNode )
+                nAnchorTxtNdNumInRange--;
+
             if ( !bAnchorTxtNdFound )
             {
                 // This case can *not* happen, but to be robust take the first
commit 6735f18c286b43fb69496114032689fcbdb0898a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 21:42:30 2014 +0200

    Normalize SwDBManager::Merge{MailFiles,Documents}
    
    There is still a difference, if run mail merge throught one or
    the other function (MM wizard or UNO).
    
    Change-Id: Ia372bd3edea4c8dfb58e045fc8fed2efcb2a4fde

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 61bfd68..0601873 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -942,21 +942,23 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
                 //copy the styles from the source to the target document
                 pTargetView->GetDocShell()->_LoadStyles( *pSourceDocSh, true );
+
                 //determine the page style and number used at the start of the source document
                 pSourceShell->SttEndDoc(true);
                 nStartingPageNo = pSourceShell->GetVirtPageNum();
                 sStartingPageDesc = sModifiedStartingPageDesc = pSourceShell->GetPageDesc(
                                             pSourceShell->GetCurPageDesc()).GetName();
-                // copy compatibility options
-                lcl_CopyCompatibilityOptions( *pSourceShell, *pTargetShell);
-                // #72821# copy dynamic defaults
-                lcl_CopyDynamicDefaults( *pSourceShell->GetDoc(), *pTargetShell->GetDoc() );
+
                 // #i72517#
                 const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
                 const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
                 bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
                                                 rMaster.GetFooter().IsActive();
 
+                // copy compatibility options
+                lcl_CopyCompatibilityOptions( *pSourceShell, *pTargetShell);
+                // #72821# copy dynamic defaults
+                lcl_CopyDynamicDefaults( *pSourceShell->GetDoc(), *pTargetShell->GetDoc() );
             }
 
             PrintMonitor aPrtMonDlg(&pSourceShell->GetView().GetEditWin(), PrintMonitor::MONITOR_TYPE_PRINT);
@@ -1046,18 +1048,25 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
 #endif
 
-                        {
                             //create a view frame for the document
-                            SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
+                            SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() );
                             //request the layout calculation
-                            SwWrtShell& rWorkShell =
-                                    static_cast< SwView* >(pWorkFrame->GetViewShell())->GetWrtShell();
-                            rWorkShell.CalcLayout();
-                            SwDoc* pWorkDoc = ((SwDocShell*)(&xWorkDocSh))->GetDoc();
+                            SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
+                            pWorkView->AttrChangedNotify( &rWorkShell );// in order for SelectShell to be called
+
+                            SwDoc* pWorkDoc = rWorkShell.GetDoc();
                             SwDBManager* pOldDBManager = pWorkDoc->GetDBManager();
                             pWorkDoc->SetDBManager( this );
+                            pWorkDoc->EmbedAllLinks();
+
+                            // #i69485# lock fields to prevent access to the result set while calculating layout
+                            rWorkShell.LockExpFlds();
+                            rWorkShell.CalcLayout();
+                            rWorkShell.UnlockExpFlds();
+
                             SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh));
-                            pWorkDoc->UpdateFlds(NULL, false);
+//                            pWorkDoc->UpdateFlds(NULL, false);
+                            rWorkShell.SwViewShell::UpdateFlds();
                             SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh));
 
                             pWorkDoc->RemoveInvisibleContent();
@@ -1226,7 +1235,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 }
                             }
                             pWorkDoc->SetDBManager( pOldDBManager );
-                        }
+
                         xWorkDocSh->DoClose();
                     }
                 }
@@ -2728,7 +2737,8 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
 
     SwWrtShell& rSourceShell = rSourceView.GetWrtShell();
     bool bSynchronizedDoc = rSourceShell.IsLabelDoc() && rSourceShell.GetSectionFmtCount() > 1;
-    //save the settings of the first
+
+    //determine the page style and number used at the start of the source document
     rSourceShell.SttEndDoc(true);
     sal_uInt16 nStartingPageNo = rSourceShell.GetVirtPageNum();
     OUString sModifiedStartingPageDesc;
@@ -2752,11 +2762,13 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
 
         SwView* pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
         rMMConfig.SetTargetView(pTargetView);
+
         //initiate SelectShell() to create sub shells
         pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
         SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr();
         SwDoc* pTargetDoc = pTargetShell->GetDoc();
 
+        //copy the styles from the source to the target document
         pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), true );
 
         // #i63806#
@@ -2807,6 +2819,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 SwDBManager* pWorkDBManager = pWorkDoc->GetDBManager();
                 pWorkDoc->SetDBManager( this );
                 pWorkDoc->EmbedAllLinks();
+
                 SwUndoId nLastUndoId(UNDO_EMPTY);
                 if (rWorkShell.GetLastUndoInfo(0, & nLastUndoId))
                 {
@@ -2815,14 +2828,16 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                         rWorkShell.Undo();
                     }
                 }
+
                 // #i69485# lock fields to prevent access to the result set while calculating layout
                 rWorkShell.LockExpFlds();
                 // create a layout
                 rWorkShell.CalcLayout();
                 rWorkShell.UnlockExpFlds();
-                SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
+
+            SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
             rWorkShell.SwViewShell::UpdateFlds();
-                SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
+            SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
 
             // strip invisible content and convert fields to text
             rWorkShell.RemoveInvisibleContent();
@@ -2843,7 +2858,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 //create a new pagestyle
                 //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
                 OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
-                pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
+                pTargetDoc->MakePageDesc( sNewPageDescName );
                 pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
                 const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
 
@@ -2857,9 +2872,6 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             else
                 pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
 
-            if(nDocNo == 1)
-                pTargetShell->SetPageStyle( sModifiedStartingPageDesc );
-
             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
             OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
 
commit 7ce8a0e682167edd6e79362a5deba4db729cf0a1
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 21:37:11 2014 +0200

    MM: Use SwDoc::Append for SwFeShell::Paste
    
    Same as the SwDBManager::MergeDocuments change.
    
    Change-Id: I44684bce187bb949dafc35a49b0aea9b46465cda

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 4bc0d0e..61bfd68 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -921,6 +921,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             OUString sStartingPageDesc;
             sal_uInt16 nStartingPageNo = 0;
             bool bPageStylesWithHeaderFooter = false;
+            SwDoc* pTargetDoc;
+
             if(bAsSingleFile || rMergeDescriptor.bCreateSingleFile)
             {
                 // create a target docshell to put the merged document into
@@ -936,6 +938,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 //initiate SelectShell() to create sub shells
                 pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
                 pTargetShell = pTargetView->GetWrtShellPtr();
+                pTargetDoc = pTargetShell->GetDoc();
+
                 //copy the styles from the source to the target document
                 pTargetView->GetDocShell()->_LoadStyles( *pSourceDocSh, true );
                 //determine the page style and number used at the start of the source document
@@ -1079,62 +1083,37 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 }
 
                                 // insert the document into the target document
-                                rWorkShell.SttEndDoc(false);
-                                rWorkShell.SttEndDoc(true);
-                                rWorkShell.SelAll();
-                                pTargetShell->SwCrsrShell::SttEndDoc( false );
-                                //#i72517# the headers and footers are still those from the source - update in case of fields inside header/footer
-                                if( !nDocNo && bPageStylesWithHeaderFooter )
-                                    pTargetShell->GetView().GetDocShell()->_LoadStyles( *rWorkShell.GetView().GetDocShell(), true );
+
                                 //#i72517# put the styles to the target document
                                 //if the source uses headers or footers each new copy need to copy a new page styles
+                                SwPageDesc* pTargetPageDesc;
                                 if(bPageStylesWithHeaderFooter)
                                 {
                                     //create a new pagestyle
                                     //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
-
-                                    SwDoc* pTargetDoc = pTargetShell->GetDoc();
-                                    SwPageDesc* pSourcePageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
                                     OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
                                     pTargetDoc->MakePageDesc( sNewPageDescName );
-                                    SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
-                                    if(pSourcePageDesc && pTargetPageDesc)
+                                    pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
+                                    const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
+
+                                    if(pWorkPageDesc && pTargetPageDesc)
                                     {
-                                        pTargetDoc->CopyPageDesc( *pSourcePageDesc, *pTargetPageDesc, false );
+                                        pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, false );
                                         sModifiedStartingPageDesc = sNewPageDescName;
-                                        lcl_CopyFollowPageDesc( *pTargetShell, *pSourcePageDesc, *pTargetPageDesc, nDocNo );
+                                        lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
                                     }
                                 }
-
-                                if(nDocNo > 1)
-                                    pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
                                 else
-                                    pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
-                                OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
-                                //#i51359# add a second paragraph in case there's only one
-                                {
-                                    SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
-                                    SwPosition aTestPos( aIdx );
-                                    SwCursor aTestCrsr(aTestPos,0,false);
-                                    if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
-                                    {
-                                        //append a paragraph
-                                        pWorkDoc->AppendTxtNode( aTestPos );
-                                    }
-                                }
+                                    pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
 
 #ifdef DBG_UTIL
                                 if ( nDocNo <= MAX_DOC_DUMP )
                                     lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
 #endif
-                                pTargetShell->Paste( rWorkShell.GetDoc(), true );
+                                pTargetDoc->Append( *(rWorkShell.GetDoc()), nStartingPageNo, pTargetPageDesc, nDocNo == 1 );
 
                                 //convert fields in page styles (header/footer - has to be done after the first document has been pasted
-                                if(1 == nDocNo)
-                                {
-                                    pTargetShell->CalcLayout();
-                                    pTargetShell->ConvertFieldsToText();
-                                }
+                                pTargetShell->CalcLayout();
 #ifdef DBG_UTIL
                                 if ( nDocNo <= MAX_DOC_DUMP )
                                     lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
commit a2b69ae97f8cd6f275c8b1064118a5c9dbb0ed4e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 21:31:35 2014 +0200

    Add debug documents to SwDBManager::MergeMailFiles
    
    Just like the debug documents in SwDBManager::MergeDocuments.
    
    Change-Id: I275575853c80d4e19d6df5ba9d8dc689353d7c85

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 71b51af..4bc0d0e 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -808,6 +808,33 @@ static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
     rWorkShell.SetLabelDoc( false );
 }
 
+#ifdef DBG_UTIL
+
+#define MAX_DOC_DUMP 3
+
+static void lcl_SaveDoc( SfxObjectShell *xTargetDocShell,
+                         const char *name, int no = 0 )
+{
+    boost::scoped_ptr< utl::TempFile > aTempFile;
+    OUString sExt( ".odt" );
+    OUString basename = OUString::createFromAscii( name );
+    if (no > 0 )
+        basename += OUString::number(no) + "-";
+    aTempFile.reset( new utl::TempFile( basename, true, &sExt ) );
+    OSL_ENSURE( aTempFile.get(), "Temporary file not available" );
+    INetURLObject aTempFileURL( aTempFile->GetURL() );
+    SfxMedium* pDstMed = new SfxMedium(
+        aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
+        STREAM_STD_READWRITE );
+    xTargetDocShell->DoSaveAs( *pDstMed );
+    xTargetDocShell->DoSaveCompleted( pDstMed );
+    if( xTargetDocShell->GetError() )
+        SAL_WARN( "sw.mailmerge", "Error saving: " << aTempFile->GetURL() );
+    else
+        SAL_INFO( "sw.mailmerge", "Saved doc as: " << aTempFile->GetURL() );
+}
+#endif
+
 bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         const SwMergeDescriptor& rMergeDescriptor)
 {
@@ -899,6 +926,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 // create a target docshell to put the merged document into
                 xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD );
                 xTargetDocShell->DoInitNew( 0 );
+#ifdef DBG_UTIL
+                lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
+#endif
                 SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
 
                 pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
@@ -1007,6 +1037,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
                         // copy the source document
                         SfxObjectShellLock xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true );
+#ifdef DBG_UTIL
+                        if ( nDocNo <= MAX_DOC_DUMP )
+                            lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
+#endif
 
                         {
                             //create a view frame for the document
@@ -1088,6 +1122,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                         pWorkDoc->AppendTxtNode( aTestPos );
                                     }
                                 }
+
+#ifdef DBG_UTIL
+                                if ( nDocNo <= MAX_DOC_DUMP )
+                                    lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
+#endif
                                 pTargetShell->Paste( rWorkShell.GetDoc(), true );
 
                                 //convert fields in page styles (header/footer - has to be done after the first document has been pasted
@@ -1096,6 +1135,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                     pTargetShell->CalcLayout();
                                     pTargetShell->ConvertFieldsToText();
                                 }
+#ifdef DBG_UTIL
+                                if ( nDocNo <= MAX_DOC_DUMP )
+                                    lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
+#endif
                             }
                             else
                             {
@@ -2648,33 +2691,6 @@ uno::Reference<XResultSet> SwDBManager::createCursor(const OUString& _sDataSourc
     return xResultSet;
 }
 
-#ifdef DBG_UTIL
-
-#define MAX_DOC_DUMP 3
-
-static void lcl_SaveDoc( SfxObjectShell *xTargetDocShell,
-                         const char *name, int no = 0 )
-{
-    boost::scoped_ptr< utl::TempFile > aTempFile;
-    OUString sExt( ".odt" );
-    OUString basename = OUString::createFromAscii( name );
-    if (no > 0 )
-        basename += OUString::number(no) + "-";
-    aTempFile.reset( new utl::TempFile( basename, true, &sExt ) );
-    OSL_ENSURE( aTempFile.get(), "Temporary file not available" );
-    INetURLObject aTempFileURL( aTempFile->GetURL() );
-    SfxMedium* pDstMed = new SfxMedium(
-        aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
-        STREAM_STD_READWRITE );
-    xTargetDocShell->DoSaveAs( *pDstMed );
-    xTargetDocShell->DoSaveCompleted( pDstMed );
-    if( xTargetDocShell->GetError() )
-        SAL_WARN( "sw.mailmerge", "Error saving: " << aTempFile->GetURL() );
-    else
-        SAL_INFO( "sw.mailmerge", "Saved doc as: " << aTempFile->GetURL() );
-}
-#endif
-
 // merge all data into one resulting document and return the number of merged documents
 sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                             SwView& rSourceView )
commit ffb27f574e43f2317acf9bf4d9832d49253e290b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 15:48:01 2014 +0200

    Add debug messages for sw.{createcopy,docappend}
    
    This adds a lot of SAL_INFO messages to SwDoc::CreateCopy and
    SwDoc::Append.
    
    Change-Id: Ie924e20698bec84482fcc5496175a9e29245729e

diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index df1d322..bc8e403 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -986,6 +986,11 @@ void SwDoc::ReplaceCompatabilityOptions(const SwDoc& rSource)
     m_pDocumentSettingManager->ReplaceCompatibilityOptions(rSource.GetDocumentSettingManager());
 }
 
+#define CNTNT_DOC( doc ) \
+    ((doc)->GetNodes().GetEndOfContent().GetIndex() - (doc)->GetNodes().GetEndOfExtras().GetIndex() - 2)
+#define CNTNT_IDX( idx ) \
+    ((idx).GetNode().GetIndex() - GetNodes().GetEndOfExtras().GetIndex() - 1)
+
 SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 {
     SwDoc* pRet = new SwDoc;
@@ -1009,7 +1014,14 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
     pRet->ReplaceStyles(*this);
 
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.createcopy", "CC-Nd-Src: " << CNTNT_DOC( this ) );
+    SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
+#endif
     pRet->Append(*this, 0, NULL, bCallInitNew);
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
+#endif
 
     // remove the temporary shell if it is there as it was done before
     pRet->SetTmpDocShell( (SfxObjectShell*) NULL );
@@ -1040,9 +1052,35 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
     else
         aCpyPam = SwPaM( aSourceIdx, aSourceEndIdx );
 
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType()
+                              << std::dec << " " << aSourceIdx.GetNode().GetIndex() );
+    aSourceIdx++;
+    SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType()
+                                            << std::dec << " " << aSourceIdx.GetNode().GetIndex() );
+    if ( aSourceIdx.GetNode().GetNodeType() != ND_ENDNODE ) {
+        aSourceIdx++;
+        SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType() << std::dec );
+        aSourceIdx--;
+    }
+    aSourceIdx--;
+    SAL_INFO( "sw.docappend", ".." );
+    SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
+                              << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
+    aSourceEndIdx++;
+    SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
+                              << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
+    aSourceEndIdx--;
+    SAL_INFO( "sw.docappend", "Src-Nd: " << CNTNT_DOC( &rSource ) );
+    SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
+#endif
+
     SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell();
     sal_uInt16 nPhysPageNumber = 0;
     if ( pTargetShell ) {
+#ifdef DBG_UTIL
+        SAL_INFO( "sw.docappend", "Has target write shell" );
+#endif
         pTargetShell->StartAllAction();
 
         // Otherwise we have to handle SwDummySectionNodes as first node
@@ -1059,7 +1097,13 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
         // We always start on an odd physical page number
         if (1 == nPhysPageNumber % 2)
             nPhysPageNumber++;
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "PPNo " << nPhysPageNumber );
+#endif
     }
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
+#endif
 
     // -1, otherwise aFixupIdx would move to new EOC
     SwNodeIndex aFixupIdx( GetNodes().GetEndOfContent(), -1 );
@@ -1068,6 +1112,13 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
     SwNodeIndex aTargetIdx( GetNodes().GetEndOfContent() );
     SwPaM aInsertPam( aTargetIdx );
 
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "Pam-Nd: " << aCpyPam.GetNode( true ).GetIndex() - aCpyPam.GetNode( false ).GetIndex() + 1
+                              << " (0x" << std::hex << (int) aCpyPam.GetNode( false ).GetNodeType() << std::dec
+                              << " " << aCpyPam.GetNode( false ).GetIndex()
+                              << " - 0x" << std::hex << (int) aCpyPam.GetNode( true ).GetNodeType() << std::dec
+                              << " " << aCpyPam.GetNode( true ).GetIndex() << ")" );
+#endif
 
     GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
     LockExpFlds();
@@ -1083,9 +1134,14 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
             SwNodeIndex aIndexBefore(rInsPos.nNode);
 
             aIndexBefore--;
-
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "CopyRange In: " << CNTNT_DOC( this ) );
+#endif
             rSource.CopyRange( aCpyPam, rInsPos, true );
             // Note: aCpyPam is invalid now
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "CopyRange Out: " << CNTNT_DOC( this ) );
+#endif
 
             ++aIndexBefore;
             SwPaM aPaM(SwPosition(aIndexBefore),
@@ -1114,10 +1170,23 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
             if ( nStartPageNumber || pTargetPageDesc ) {
                 // Changes the index of aFixupIdx
                 SwTxtNode *aTxtNd = dynamic_cast<  SwTxtNode* >( GetNodes().GoNext(&aFixupIdx) );
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "Idx " << CNTNT_IDX( aDelIdx ) );
+    SAL_INFO( "sw.docappend", "Idx " << CNTNT_IDX( aFixupIdx ) );
+#endif
                 if ( aTxtNd ) {
                     SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "Which: " << pNewItem->Which() << " " << RES_PAGEDESC );
+#endif
                     SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
                     if ( aDesc ) {
+#ifdef DBG_UTIL
+if ( aDesc->GetPageDesc() )
+        SAL_INFO( "sw.docappend", "PD Update " << aDesc->GetPageDesc()->GetName() );
+else
+        SAL_INFO( "sw.docappend", "PD New" );
+#endif
                         if ( nStartPageNumber )
                             aDesc->SetNumOffset( nStartPageNumber );
                         if ( pTargetPageDesc )
@@ -1126,6 +1195,10 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
                     }
                     delete pNewItem;
                 }
+
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "Idx " << CNTNT_IDX( aDelIdx ) );
+#endif
                 iDelNodes++;
             }
 
@@ -1139,6 +1212,11 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
                 if ( pTargetShell )
                     pTargetShell->SttEndDoc( false );
                 aDelIdx -= (iDelNodes - 1);
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "iDelNodes: " << iDelNodes
+                              << "  Idx: " << aDelIdx.GetNode().GetIndex()
+                              << "  EOE: " << GetNodes().GetEndOfExtras().GetIndex() );
+#endif
                 GetNodes().Delete( aDelIdx, iDelNodes );
             }
         }
@@ -1151,6 +1229,10 @@ void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
             SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
             if (FLY_AT_PAGE != aAnchor.GetAnchorId())
                 continue;
+#ifdef DBG_UTIL
+    SAL_INFO( "sw.docappend", "PaAn: " << aAnchor.GetPageNum()
+                              << " => " << aAnchor.GetPageNum() + nPhysPageNumber );
+#endif
             if ( nPhysPageNumber )
                 aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber );
             CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
commit ed4ab7afbb68f304661d8de37cfff78dd380b59e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 13:02:58 2014 +0200

    Refactor NumRule handling in CopyImpl
    
    The bug fix for i#86492 added a lot of duplicated code. This moves
    the code into their own functions and uses macros to make the
    resulting code even more readable.
    
    Change-Id: Ifa0ece26f3152f1f8d8c65173b459e8c14c5b43a

diff --git a/sw/source/core/docnode/ndcopy.cxx b/sw/source/core/docnode/ndcopy.cxx
index 1f49b0d..5443c9f 100644
--- a/sw/source/core/docnode/ndcopy.cxx
+++ b/sw/source/core/docnode/ndcopy.cxx
@@ -849,6 +849,69 @@ static bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
     return bRet;
 }
 
+#define NUMRULE_STATE \
+     int aNumRuleState = SFX_ITEM_UNKNOWN; \
+     SwNumRuleItem aNumRuleItem; \
+     int aListIdState = SFX_ITEM_UNKNOWN; \
+     SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() ); \
+
+#define PUSH_NUMRULE_STATE \
+     lcl_PushNumruleState( aNumRuleState, aNumRuleItem, aListIdState, aListIdItem, pDestTxtNd );
+
+#define POP_NUMRULE_STATE \
+     lcl_PopNumruleState( aNumRuleState, aNumRuleItem, aListIdState, aListIdItem, pDestTxtNd, rPam );
+
+static void lcl_PushNumruleState( int &aNumRuleState, SwNumRuleItem &aNumRuleItem,
+                                  int &aListIdState, SfxStringItem &aListIdItem,
+                                  const SwTxtNode *pDestTxtNd )
+{
+    // Safe numrule item at destination.
+    // #i86492# - Safe also <ListId> item of destination.
+    const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
+    if (pAttrSet != NULL)
+    {
+        const SfxPoolItem * pItem = NULL;
+        aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
+        if (SFX_ITEM_SET == aNumRuleState)
+            aNumRuleItem = *((SwNumRuleItem *) pItem);
+
+        aListIdState =
+            pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
+        if (SFX_ITEM_SET == aListIdState)
+        {
+            aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+        }
+    }
+}
+
+static void lcl_PopNumruleState( int aNumRuleState, const SwNumRuleItem &aNumRuleItem,
+                                 int aListIdState, const SfxStringItem &aListIdItem,
+                                 SwTxtNode *pDestTxtNd, const SwPaM& rPam )
+{
+    /* If only a part of one paragraph is copied
+       restore the numrule at the destination. */
+    // #i86492# - restore also <ListId> item
+    if ( !lcl_MarksWholeNode(rPam) )
+    {
+        if (SFX_ITEM_SET == aNumRuleState)
+        {
+            pDestTxtNd->SetAttr(aNumRuleItem);
+        }
+        else
+        {
+            pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
+        }
+        if (SFX_ITEM_SET == aListIdState)
+        {
+            pDestTxtNd->SetAttr(aListIdItem);
+        }
+        else
+        {
+            pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
+        }
+    }
+}
+
 bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
         const bool bMakeNewFrms, const bool bCopyAll,
         SwPaM *const pCpyRange ) const
@@ -1012,28 +1075,10 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
                     }
                 }
 
-                // Safe numrule item at destination.
-                // #i86492# - Safe also <ListId> item of destination.
-                int aNumRuleState = SFX_ITEM_UNKNOWN;
-                SwNumRuleItem aNumRuleItem;
-                int aListIdState = SFX_ITEM_UNKNOWN;
-                SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
+                NUMRULE_STATE
+                if( bCopyCollFmt && bOneNode )
                 {
-                    const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
-                    if (pAttrSet != NULL)
-                    {
-                        const SfxPoolItem * pItem = NULL;
-                        aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
-                        if (SFX_ITEM_SET == aNumRuleState)
-                            aNumRuleItem = *((SwNumRuleItem *) pItem);
-
-                        aListIdState =
-                            pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
-                        if (SFX_ITEM_SET == aListIdState)
-                        {
-                            aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
-                        }
-                    }
+                    PUSH_NUMRULE_STATE
                 }
 
                 if( !bCopyOk )
@@ -1053,29 +1098,7 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
                     if( bCopyCollFmt )
                     {
                         pSttTxtNd->CopyCollFmt( *pDestTxtNd );
-
-                        /* If only a part of one paragraph is copied
-                           restore the numrule at the destination. */
-                        // #i86492# - restore also <ListId> item
-                        if ( !lcl_MarksWholeNode(rPam) )
-                        {
-                            if (SFX_ITEM_SET == aNumRuleState)
-                            {
-                                pDestTxtNd->SetAttr(aNumRuleItem);
-                            }
-                            else
-                            {
-                                pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
-                            }
-                            if (SFX_ITEM_SET == aListIdState)
-                            {
-                                pDestTxtNd->SetAttr(aListIdItem);
-                            }
-                            else
-                            {
-                                pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
-                            }
-                        }
+                        POP_NUMRULE_STATE
                     }
 
                     break;
@@ -1157,31 +1180,14 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
                 bStartIsTxtNode = true;
             }
 
-            // Save numrule at destination
-            // #i86492# - Safe also <ListId> item of destination.
-            int aNumRuleState = SFX_ITEM_UNKNOWN;
-            SwNumRuleItem aNumRuleItem;
-            int aListIdState = SFX_ITEM_UNKNOWN;
-            SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
-            {
-                const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
-                if (pAttrSet != NULL)
-                {
-                    const SfxPoolItem * pItem = NULL;
-
-                    aNumRuleState =
-                        pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
-                    if (SFX_ITEM_SET == aNumRuleState)
-                        aNumRuleItem = *((SwNumRuleItem *) pItem);
+            const bool bEmptyDestNd = pDestTxtNd->GetTxt().isEmpty();
 
-                    aListIdState =
-                        pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
-                    if (SFX_ITEM_SET == aListIdState)
-                        aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
-                }
+            NUMRULE_STATE
+            if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
+            {
+                PUSH_NUMRULE_STATE
             }
 
-            const bool bEmptyDestNd = pDestTxtNd->GetTxt().isEmpty();
             pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
                             pEnd->nContent.GetIndex() );
 
@@ -1189,31 +1195,9 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
             if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
             {
                 pEndTxtNd->CopyCollFmt( *pDestTxtNd );
-
                 if ( bOneNode )
                 {
-                    /* If only a part of one paragraph is copied
-                       restore the numrule at the destination. */
-                    // #i86492# - restore also <ListId> item
-                    if ( !lcl_MarksWholeNode(rPam) )
-                    {
-                        if (SFX_ITEM_SET == aNumRuleState)
-                        {
-                            pDestTxtNd->SetAttr(aNumRuleItem);
-                        }
-                        else
-                        {
-                            pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
-                        }
-                        if (SFX_ITEM_SET == aListIdState)
-                        {
-                            pDestTxtNd->SetAttr(aListIdItem);
-                        }
-                        else
-                        {
-                            pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
-                        }
-                    }
+                    POP_NUMRULE_STATE
                 }
             }
         }
commit 475ec9953cc5c45e4a773bba0006410ce49adb6a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Jul 1 15:25:10 2014 +0200

    Fixup SwDoc::Append
    
    Change-Id: I84ee5290ded20803d1496daa52325c3651a9bc97

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index ec80dd3..d0e31aa 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1885,8 +1885,8 @@ public:
     ::sw::UndoManager const& GetUndoManager() const;
 
     SfxObjectShell* CreateCopy(bool bCallInitNew) const;
-    void Append( const SwDoc& rSource, int nStartPageNumber,
-                 SwPageDesc* pTargetPageDesc, int nPhysPageNumber );
+    void Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
+                 SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false );
 
     /**
      * Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by default)
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 54fa8bc..df1d322 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -92,6 +92,7 @@
 #include <DocumentDrawModelManager.hxx>
 #include <unochart.hxx>
 #include <fldbas.hxx>
+#include <wrtsh.hxx>
 
 #include <cmdid.h>
 
@@ -1008,13 +1009,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
     pRet->ReplaceStyles(*this);
 
-    pRet->Append(*this, 0, NULL, 0);
-
-    if ( bCallInitNew ) {
-        // delete leading page / initial content from target document
-        SwNodeIndex aDeleteIdx( pRet->GetNodes().GetEndOfExtras(), 2 );
-        pRet->GetNodes().Delete( aDeleteIdx, 1 );
-    }
+    pRet->Append(*this, 0, NULL, bCallInitNew);
 
     // remove the temporary shell if it is there as it was done before
     pRet->SetTmpDocShell( (SfxObjectShell*) NULL );
@@ -1025,20 +1020,54 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 }
 
 // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
-void SwDoc::Append( const SwDoc& rSource, int nStartPageNumber,
-                    SwPageDesc* pTargetPageDesc, int nPhysPageNumber )
+void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
+                    SwPageDesc* pTargetPageDesc, bool bDeletePrevious )
 {
-    // GetEndOfExtras + 1 = StartOfContent
+    // GetEndOfExtras + 1 = StartOfContent == no content node!
+    // this prevents CopyRange to merge any starting text nodes of the first
+    // source paragraph!
+    // additionally it ensures, that we have at least two nodes in the SwPaM.
     SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 );
-    SwPaM aCpyPam( aSourceIdx ); //DocStart
+    SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), -1 );
+    SwPaM aCpyPam( aSourceIdx );
+
+    if ( aSourceEndIdx.GetNode().IsTxtNode() ) {
+        aCpyPam.SetMark();
+        // moves to the last content node before EOC; for single paragraph
+        // documents this would result in [n, n], which is considered empty
+        aCpyPam.Move( fnMoveForward, fnGoDoc );
+    }
+    else
+        aCpyPam = SwPaM( aSourceIdx, aSourceEndIdx );
+
+    SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell();
+    sal_uInt16 nPhysPageNumber = 0;
+    if ( pTargetShell ) {
+        pTargetShell->StartAllAction();
+
+        // Otherwise we have to handle SwDummySectionNodes as first node
+        if ( pTargetPageDesc ) {
+            OUString name = pTargetPageDesc->GetName();
+            pTargetShell->InsertPageBreak( &name, nStartPageNumber );
+        }
+
+        // -1 for the page break + -1, becauce it's an offset
+        nPhysPageNumber = pTargetShell->GetPhyPageNum() - 2;
+        if (bDeletePrevious)
+            nPhysPageNumber--;
 
-    // Append at the end of document / content
+        // We always start on an odd physical page number
+        if (1 == nPhysPageNumber % 2)
+            nPhysPageNumber++;
+    }
+
+    // -1, otherwise aFixupIdx would move to new EOC
+    SwNodeIndex aFixupIdx( GetNodes().GetEndOfContent(), -1 );
+
+    // append at the end of document / content
     SwNodeIndex aTargetIdx( GetNodes().GetEndOfContent() );
-    SwPaM aInsertPam( aTargetIdx ); //replaces PCURCRSR from SwFEShell::Paste()
-    aTargetIdx--;
+    SwPaM aInsertPam( aTargetIdx );
 
-    aCpyPam.SetMark();
-    aCpyPam.Move( fnMoveForward, fnGoDoc );
 
     GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
     LockExpFlds();
@@ -1077,24 +1106,44 @@ void SwDoc::Append( const SwDoc& rSource, int nStartPageNumber,
             }
         }
 
-        // update the PageDesc pool item
-        if ( nStartPageNumber || pTargetPageDesc ) {
-            SwTxtNode *aTxtNd = dynamic_cast<  SwTxtNode* >( GetNodes().GoNext(&aTargetIdx) );
-            if ( aTxtNd ) {
-                SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
-                SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
-                if ( aDesc ) {
-                    if ( nStartPageNumber )
-                        aDesc->SetNumOffset( nStartPageNumber );
-                    if ( pTargetPageDesc )
-                        aDesc->RegisterToPageDesc( *pTargetPageDesc );
-                    aTxtNd->SetAttr( *aDesc );
+        {
+            sal_uInt16 iDelNodes = 0;
+            SwNodeIndex aDelIdx( aFixupIdx );
+
+            // update the PageDesc format item
+            if ( nStartPageNumber || pTargetPageDesc ) {
+                // Changes the index of aFixupIdx
+                SwTxtNode *aTxtNd = dynamic_cast<  SwTxtNode* >( GetNodes().GoNext(&aFixupIdx) );
+                if ( aTxtNd ) {
+                    SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
+                    SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
+                    if ( aDesc ) {
+                        if ( nStartPageNumber )
+                            aDesc->SetNumOffset( nStartPageNumber );
+                        if ( pTargetPageDesc )
+                            aDesc->RegisterToPageDesc( *pTargetPageDesc );
+                        aTxtNd->SetAttr( *aDesc );
+                    }
+                    delete pNewItem;
                 }
-                delete pNewItem;
+                iDelNodes++;
+            }
+
+            if ( bDeletePrevious )
+                iDelNodes++;
+
+            if ( iDelNodes ) {
+                // delete leading empty page(s), e.g. from InsertPageBreak or
+                // new SwDoc. this has to be done before copying the page bound
+                // frames, otherwise the drawing layer gets confused.
+                if ( pTargetShell )
+                    pTargetShell->SttEndDoc( false );
+                aDelIdx -= (iDelNodes - 1);
+                GetNodes().Delete( aDelIdx, iDelNodes );
             }
         }
 
-        // additionally copy page bound frames
+        // finally copy page bound frames
         const SwFrmFmts *pSpzFrmFmts = rSource.GetSpzFrmFmts();
         for ( sal_uInt16 i = 0; i < pSpzFrmFmts->size(); ++i )
         {
@@ -1102,7 +1151,7 @@ void SwDoc::Append( const SwDoc& rSource, int nStartPageNumber,
             SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
             if (FLY_AT_PAGE != aAnchor.GetAnchorId())
                 continue;
-            if ( nStartPageNumber )
+            if ( nPhysPageNumber )
                 aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber );
             CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
         }
@@ -1112,6 +1161,9 @@ void SwDoc::Append( const SwDoc& rSource, int nStartPageNumber,
 
     UnlockExpFlds();
     UpdateFlds(NULL, false);
+
+    if ( pTargetShell )
+        pTargetShell->EndAllAction();
 }
 
 sal_uInt16 SwTxtFmtColls::GetPos(const SwTxtFmtColl* p) const
diff --git a/sw/source/core/docnode/ndcopy.cxx b/sw/source/core/docnode/ndcopy.cxx
index 5575934..1f49b0d 100644
--- a/sw/source/core/docnode/ndcopy.cxx
+++ b/sw/source/core/docnode/ndcopy.cxx
@@ -1355,8 +1355,10 @@ void SwDoc::CopyWithFlyInFly(
             !rRg.aStart.GetNode().IsSectionNode() &&
             !aTmpI.GetNode().IsEndNode() )
         {
+            // If the range starts with a SwStartNode, it isn't copied
+            sal_uInt16 offset = (rRg.aStart.GetNode().GetNodeType() != ND_STARTNODE) ? 1 : 0;
             OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
-                    rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
+                    rRg.aEnd.GetIndex() - rRg.aStart.GetIndex() - 1 + offset,
                     "An insufficient number of nodes were copied!" );
         }
     }
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index e8e63db..71b51af 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2769,7 +2769,6 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
         const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
         bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
                                         rMaster.GetFooter().IsActive();
-        SwNodes *pTargetNodes = &pTargetShell->GetDoc()->GetNodes();
 
         // copy compatibility options
         lcl_CopyCompatibilityOptions( rSourceShell, *pTargetShell);
@@ -2840,10 +2839,6 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             }
 
             // insert the document into the target document
-            rWorkShell.SttEndDoc(false);
-            rWorkShell.SttEndDoc(true);
-            rWorkShell.SelAll();
-            pTargetShell->SttEndDoc(false);
 
             //#i63806# put the styles to the target document
             //if the source uses headers or footers each new copy need to copy a new page styles
@@ -2868,7 +2863,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
 
             if(nDocNo == 1)
-                pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
+                pTargetShell->SetPageStyle( sModifiedStartingPageDesc );
 
             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
             OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
@@ -2877,18 +2872,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             if ( nDocNo <= MAX_DOC_DUMP )
                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
 #endif
-
-            if (nDocNo == 1 ) {
-                pTargetDoc->Append( *(rWorkShell.GetDoc()), 0, pTargetPageDesc, 0 );
-
-                // delete the leading empty page from the initial SwDoc
-                pTargetShell->SttEndDoc( false );
-                SwNodeIndex aDeleteIdx( pTargetNodes->GetEndOfExtras(), 2 );
-                pTargetNodes->Delete( aDeleteIdx, 1 );
-            }
-            else
-                pTargetDoc->Append( *(rWorkShell.GetDoc()), nStartingPageNo,
-                                    pTargetPageDesc, pTargetShell->GetPhyPageNum() );
+            pTargetDoc->Append( *(rWorkShell.GetDoc()), nStartingPageNo, pTargetPageDesc, nDocNo == 1 );
 
             // #i72820# calculate layout to be able to find the correct page index
             pTargetShell->CalcLayout();
commit 68fe2949f3297b2fc2d2c513c04562fec3df60a8
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Sat Jun 28 01:41:17 2014 +0200

    MM: introduce SwDoc::Append helper function
    
    This drops all the specialized, workaround code from MM, introduced
    to use the SwFEShell::Paste function.
    
    There is still a little common codepath, therefore this adds
    comments to always update both functions.
    
    Change-Id: I704b3ef3257dd977dac95e16e25049ff8ade97ed

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index ac31da1..ec80dd3 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1883,7 +1883,10 @@ public:
     ::sw::MetaFieldManager & GetMetaFieldManager();
     ::sw::UndoManager      & GetUndoManager();
     ::sw::UndoManager const& GetUndoManager() const;
+
     SfxObjectShell* CreateCopy(bool bCallInitNew) const;
+    void Append( const SwDoc& rSource, int nStartPageNumber,
+                 SwPageDesc* pTargetPageDesc, int nPhysPageNumber );
 
     /**
      * Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by default)
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index 2660c5a..749e735 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -219,7 +219,7 @@ public:
 
     /// Copy and Paste methods for internal clipboard.
     bool Copy( SwDoc* pClpDoc, const OUString* pNewClpTxt = 0 );
-    bool Paste( SwDoc* pClpDoc, bool bIncludingPageFrames = false, bool bIncludeFullDocument = false);
+    bool Paste( SwDoc* pClpDoc, bool bIncludingPageFrames = false );
 
     /// Paste some pages into another doc - used in mailmerge.
     bool PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage);
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 6c19998..54fa8bc 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -995,7 +995,8 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
     SfxObjectShell* pRetShell = new SwDocShell( pRet, SFX_CREATE_MODE_STANDARD );
     if( bCallInitNew )
     {
-        // it could happen that DoInitNew creates model, that increases the refcount of the object
+        // it could happen that DoInitNew creates model,
+        // that increases the refcount of the object
         pRetShell->DoInitNew();
     }
 
@@ -1007,30 +1008,54 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
     pRet->ReplaceStyles(*this);
 
-    // Based on the simplified codepath from SwFEShell::Paste()
+    pRet->Append(*this, 0, NULL, 0);
 
+    if ( bCallInitNew ) {
+        // delete leading page / initial content from target document
+        SwNodeIndex aDeleteIdx( pRet->GetNodes().GetEndOfExtras(), 2 );
+        pRet->GetNodes().Delete( aDeleteIdx, 1 );
+    }
+
+    // remove the temporary shell if it is there as it was done before
+    pRet->SetTmpDocShell( (SfxObjectShell*) NULL );
+
+    pRet->release();
+
+    return pRetShell;
+}
+
+// appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
+void SwDoc::Append( const SwDoc& rSource, int nStartPageNumber,
+                    SwPageDesc* pTargetPageDesc, int nPhysPageNumber )
+{
     // GetEndOfExtras + 1 = StartOfContent
-    SwNodeIndex aSourceIdx( GetNodes().GetEndOfExtras(), 1 );
-    SwPaM aCpyPam( aSourceIdx ); // DocStart
+    SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 );
+    SwPaM aCpyPam( aSourceIdx ); //DocStart
 
-    SwNodeIndex aTargetIdx( pRet->GetNodes().GetEndOfContent() );
-    SwPaM aInsertPam( aTargetIdx );
+    // Append at the end of document / content
+    SwNodeIndex aTargetIdx( GetNodes().GetEndOfContent() );
+    SwPaM aInsertPam( aTargetIdx ); //replaces PCURCRSR from SwFEShell::Paste()
+    aTargetIdx--;
 
     aCpyPam.SetMark();
     aCpyPam.Move( fnMoveForward, fnGoDoc );
 
-    pRet->LockExpFlds();
+    GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+    LockExpFlds();
 
     {
+        // **
+        // ** refer to SwFEShell::Paste, if you change the following code **
+        // **
+
         SwPosition& rInsPos = *aInsertPam.GetPoint();
-        SwPosition aInsertPosition( rInsPos );
 
         {
             SwNodeIndex aIndexBefore(rInsPos.nNode);
 
             aIndexBefore--;
 
-            CopyRange( aCpyPam, rInsPos, true );
+            rSource.CopyRange( aCpyPam, rInsPos, true );
             // Note: aCpyPam is invalid now
 
             ++aIndexBefore;
@@ -1039,37 +1064,54 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
             aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
 
-            // No need to update the rsid, as pRet is an empty doc
+            // Update the rsid of each pasted text node
+            SwNodes &rDestNodes = GetNodes();
+            sal_uLong const nEndIdx = aPaM.End()->nNode.GetIndex();
+
+            for (sal_uLong nIdx = aPaM.Start()->nNode.GetIndex();
+                    nIdx <= nEndIdx; ++nIdx)
+            {
+                SwTxtNode *const pTxtNode = rDestNodes[nIdx]->GetTxtNode();
+                if ( pTxtNode )
+                    UpdateParRsid( pTxtNode );
+            }
+        }
+
+        // update the PageDesc pool item
+        if ( nStartPageNumber || pTargetPageDesc ) {
+            SwTxtNode *aTxtNd = dynamic_cast<  SwTxtNode* >( GetNodes().GoNext(&aTargetIdx) );
+            if ( aTxtNd ) {
+                SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
+                SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
+                if ( aDesc ) {
+                    if ( nStartPageNumber )
+                        aDesc->SetNumOffset( nStartPageNumber );
+                    if ( pTargetPageDesc )
+                        aDesc->RegisterToPageDesc( *pTargetPageDesc );
+                    aTxtNd->SetAttr( *aDesc );
+                }
+                delete pNewItem;
+            }
         }
 
         // additionally copy page bound frames
-        for ( sal_uInt16 i = 0; i < GetSpzFrmFmts()->size(); ++i )
+        const SwFrmFmts *pSpzFrmFmts = rSource.GetSpzFrmFmts();
+        for ( sal_uInt16 i = 0; i < pSpzFrmFmts->size(); ++i )
         {
-            const SwFrmFmt& rCpyFmt = *(*GetSpzFrmFmts())[i];
+            const SwFrmFmt& rCpyFmt = *(*pSpzFrmFmts)[i];
             SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
             if (FLY_AT_PAGE != aAnchor.GetAnchorId())
                 continue;
-            pRet->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+            if ( nStartPageNumber )
+                aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber );
+            CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
         }
     }
 
-    pRet->UnlockExpFlds();
-    pRet->UpdateFlds( NULL, false );
+    GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
 
-    // End of SwFEShell::Paste() codepath
-
-    if ( bCallInitNew ) {
-        // delete leading page / initial content from target document
-        SwNodeIndex aDeleteIdx( pRet->GetNodes().GetEndOfExtras(), 2 );
-        pRet->GetNodes().Delete( aDeleteIdx, 1 );
-    }
-
-    // remove the temporary shell if it is there as it was done before
-    pRet->SetTmpDocShell( (SfxObjectShell*)NULL );
-
-    pRet->release();
-
-    return pRetShell;
+    UnlockExpFlds();
+    UpdateFlds(NULL, false);
 }
 
 sal_uInt16 SwTxtFmtColls::GetPos(const SwTxtFmtColl* p) const
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index dc4fce0..31509d0 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -668,13 +668,13 @@ namespace {
     typedef std::pair< PaMPtr, PositionPtr > Insertion;
 }
 
-bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames, bool bIncludeFullDocument )
+bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames )
 {
     SET_CURR_SHELL( this );
     OSL_ENSURE( pClpDoc, "no clipboard document"  );
     const sal_uInt16 nStartPageNumber = GetPhyPageNum();
     // then till end of the nodes array
-    SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), (bIncludeFullDocument) ? 1 : 2 );
+    SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
     SwPaM aCpyPam( aIdx ); //DocStart
 
     // If there are table formulas in the area, then display the table first
@@ -1022,6 +1022,10 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames, bool bIncludeF
                 GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
             }
 
+            // **
+            // ** Update SwDoc::Append, if you change the following code **
+            // **
+
             // find out if the clipboard document starts with a table
             bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
             SwPosition aInsertPosition( rInsPos );
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 529c3929..e8e63db 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2760,6 +2760,10 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
         //initiate SelectShell() to create sub shells
         pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
         SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr();
+        SwDoc* pTargetDoc = pTargetShell->GetDoc();
+
+        pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), true );
+
         // #i63806#
         const SwPageDesc* pSourcePageDesc = rSourceShell.FindPageDescByName( sStartingPageDesc );
         const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
@@ -2848,8 +2852,6 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             {
                 //create a new pagestyle
                 //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
-
-                SwDoc* pTargetDoc = pTargetShell->GetDoc();
                 OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
                 pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
                 pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
@@ -2862,65 +2864,31 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                     lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
                 }
             }
-            if(nDocNo == 1 || bPageStylesWithHeaderFooter)
-                pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), true );
-            if(nDocNo > 1)
-                pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
             else
+                pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
+
+            if(nDocNo == 1)
                 pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
 
             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
             OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
-            bool para_added = false;
-
-            //#i51359# add a second paragraph in case there's only one
-            {
-                SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
-                SwPosition aTestPos( aIdx );
-                SwCursor aTestCrsr( aTestPos, 0, false );
-                if ( !aTestCrsr.MovePara(fnParaNext, fnParaStart) )
-                {
-                    //append a paragraph
-                    pWorkDoc->AppendTxtNode( aTestPos );
-                    para_added = true;
-                }
-            }
 
 #ifdef DBG_UTIL
             if ( nDocNo <= MAX_DOC_DUMP )
                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
 #endif
 
-            SwNodeIndex fixupIdx( pTargetNodes->GetEndOfContent(), -1 );
-            pTargetShell->Paste( rWorkShell.GetDoc(), true, true );
-
-            if (bPageStylesWithHeaderFooter) {
-                // set the real page desc and update the number offset for the pasted document
-                fixupIdx += 2;
-                SwTxtNode *aTxtNd = fixupIdx.GetNode().GetTxtNode();
-                if ( aTxtNd ) {
-                    SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
-                    SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
-                    if ( aDesc ) {
-                        aDesc->SetNumOffset( nStartingPageNo );
-                        aDesc->RegisterToPageDesc( *pTargetPageDesc );
-                        aTxtNd->SetAttr( *aDesc );
-                    }
-                    delete pNewItem;
-                }
+            if (nDocNo == 1 ) {
+                pTargetDoc->Append( *(rWorkShell.GetDoc()), 0, pTargetPageDesc, 0 );
 
-                // delete the leading empty page from InsertPageBreak
-                fixupIdx -= 2;
-                pTargetNodes->Delete( fixupIdx, 2 );
-            }
-
-            if ( para_added ) {
-                // Move cursor to the start or Delete will assert because
-                // of the cursors SwIndex ref on the deleting node.
-                pTargetShell->SttEndDoc( true );
-                SwNodeIndex aTargetIdx( pTargetNodes->GetEndOfContent(), -1 );
-                pTargetNodes->Delete( aTargetIdx, 1 );
+                // delete the leading empty page from the initial SwDoc
+                pTargetShell->SttEndDoc( false );
+                SwNodeIndex aDeleteIdx( pTargetNodes->GetEndOfExtras(), 2 );
+                pTargetNodes->Delete( aDeleteIdx, 1 );
             }
+            else
+                pTargetDoc->Append( *(rWorkShell.GetDoc()), nStartingPageNo,
+                                    pTargetPageDesc, pTargetShell->GetPhyPageNum() );
 
             // #i72820# calculate layout to be able to find the correct page index
             pTargetShell->CalcLayout();
commit 93bb2e84a48397edeca6f95dd1e4e7eaaa349f51
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jun 23 09:27:27 2014 +0200

    MM: always copy the internal document
    
    There is really no need to create the first document via UNO
    createClone(), which is also slower then the internal copy.
    
    Actually createClone also calls createCopy, but without
    initializing the document.
    
    Change-Id: I23437b0f3ad663942a02be575b39883f9a3b8587

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index d73bb63..529c3929 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1005,17 +1005,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             Application::Reschedule();
 
                         // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
-                        SfxObjectShellLock xWorkDocSh;
                         // copy the source document
-                        if( 1 == nDocNo && (bAsSingleFile || rMergeDescriptor.bCreateSingleFile) )
-                        {
-                            uno::Reference< util::XCloneable > xClone( pSourceDocSh->GetModel(), uno::UNO_QUERY);
-                            uno::Reference< lang::XUnoTunnel > xWorkDocShell( xClone->createClone(), uno::UNO_QUERY);
-                            SwXTextDocument* pWorkModel = reinterpret_cast<SwXTextDocument*>(xWorkDocShell->getSomething(SwXTextDocument::getUnoTunnelId()));
-                            xWorkDocSh = pWorkModel->GetDocShell();
-                        }
-                        else
-                            xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true );
+                        SfxObjectShellLock xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true );
 
                         {
                             //create a view frame for the document
@@ -2802,18 +2793,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
 
             // copy the source document
             // the copy will be closed later, but it is more safe to use SfxObjectShellLock here
-            SfxObjectShellLock xWorkDocSh;
-            if(nDocNo == 1 )
-            {
-                uno::Reference< util::XCloneable > xClone( rSourceView.GetDocShell()->GetModel(), uno::UNO_QUERY);
-                uno::Reference< lang::XUnoTunnel > xWorkDocShell( xClone->createClone(), uno::UNO_QUERY);
-                SwXTextDocument* pWorkModel = reinterpret_cast<SwXTextDocument*>(xWorkDocShell->getSomething(SwXTextDocument::getUnoTunnelId()));
-                xWorkDocSh = pWorkModel->GetDocShell();
-            }
-            else
-            {
-                xWorkDocSh = rSourceView.GetDocShell()->GetDoc()->CreateCopy(true);
-            }
+            SfxObjectShellLock xWorkDocSh = rSourceView.GetDocShell()->GetDoc()->CreateCopy(true);
 #ifdef DBG_UTIL
             if ( nDocNo <= MAX_DOC_DUMP )
                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
commit 3c62106de6516959ea20fbf4c5479e07774a3ead
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jun 27 14:58:24 2014 +0200

    Some minor MM related refactoring
    
    Refactors some code of SwFEShell::Paste and
    SwDBManager::MergeDocuments to make it more readable.
    
    Change-Id: Ifd78d6a44fa78eaf1f4fca63f4bbd3ee43ca129d

diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 4b12c78..dc4fce0 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -680,7 +680,7 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames, bool bIncludeF
     // If there are table formulas in the area, then display the table first
     // so that the table formula can calculate a new value first
     // (individual boxes in the area are retrieved via the layout)
-     SwFieldType* pTblFldTyp = GetDoc()->GetSysFldType( RES_TABLEFLD );
+    SwFieldType* pTblFldTyp = GetDoc()->GetSysFldType( RES_TABLEFLD );
 
     SwTableNode *pDestNd, *pSrcNd = aCpyPam.GetNode().GetTableNode();
     if( !pSrcNd )                               // TabellenNode ?
@@ -1071,19 +1071,12 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames, bool bIncludeF
 
                 for ( sal_uInt16 i = 0; i < pClpDoc->GetSpzFrmFmts()->size(); ++i )
                 {
-                    bool bInsWithFmt = true;
                     const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i];
-                    if( bInsWithFmt  )
-                    {
-                        SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
-                        if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
-                        {
-                            aAnchor.SetPageNum( aAnchor.GetPageNum() + nStartPageNumber - 1 );
-                        }
-                        else
-                            continue;
-                        GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
-                    }
+                    SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+                    if ( FLY_AT_PAGE != aAnchor.GetAnchorId() )
+                        continue;
+                    aAnchor.SetPageNum( aAnchor.GetPageNum() + nStartPageNumber - 1 );
+                    GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
                 }
             }
         }
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index ef8d4df..d73bb63 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2883,17 +2883,12 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 }
             }
             if(nDocNo == 1 || bPageStylesWithHeaderFooter)
-            {
                 pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), true );
-            }
             if(nDocNo > 1)
-            {
                 pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
-            }
             else
-            {
                 pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
-            }
+
             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
             OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
             bool para_added = false;
@@ -2901,9 +2896,9 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             //#i51359# add a second paragraph in case there's only one
             {
                 SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
-              SwPosition aTestPos( aIdx );
-              SwCursor aTestCrsr(aTestPos,0,false);
-                if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
+                SwPosition aTestPos( aIdx );
+                SwCursor aTestCrsr( aTestPos, 0, false );
+                if ( !aTestCrsr.MovePara(fnParaNext, fnParaStart) )
                 {
                     //append a paragraph
                     pWorkDoc->AppendTxtNode( aTestPos );
@@ -2955,7 +2950,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
 #endif
 
-            //add the document info to the config item
+            // add the document info to the config item
             SwDocMergeInfo aMergeInfo;
             aMergeInfo.nStartPageInTarget = nPageCountBefore;
             aMergeInfo.nEndPageInTarget = pTargetShell->GetPageCnt();
@@ -2967,17 +2962,17 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             for( sal_uInt16 i = 0; i < 25; i++)
                 Application::Reschedule();
 
-            //restore the ole DBManager
+            // restore the old DBManager
             pWorkDoc->SetDBManager( pWorkDBManager );
-            //now the temporary document should be closed
-            SfxObjectShellRef xDocSh(pWorkView->GetDocShell());
-            xDocSh->DoClose();
+            // close the temporary document
+            xWorkDocSh->DoClose();
+
             nEndRow = pImpl->pMergeData->xResultSet->getRow();
             ++nDocNo;
         } while( !bCancel &&
                 (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
 
-        //deselect all, go out of the frame and go to the beginning of the document
+        // deselect all, go out of the frame and go to the beginning of the document
         Point aPt(LONG_MIN, LONG_MIN);
         pTargetShell->SelectObj(aPt, SW_LEAVE_FRAME);
         if (pTargetShell->IsSelFrmMode())
commit 815b3c22cf010e3b64cb879a53616cdf6a9308bb
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jun 27 11:46:00 2014 +0200

    MM: fix lost or broken paragraph anchored objects
    
    With the extended SwFEShell::Paste version, we can finally paste
    full documents without losing the paragraph anchored Flys of the
    first paragraph.
    
    Actually one should be able to drop the InsertPageBreak and the
    single paragraph delete, but my attempt resulted in problems with
    page anchored Flys and somehow reintroduced the problem seen in
    fdo#80395 with draw objects.
    
    Change-Id: I370fa89f432ba4dd95c1f02605f33f04dfbaad85

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 646a0a6..ef8d4df 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -125,6 +125,8 @@
 #include <unomid.h>
 #include <section.hxx>
 #include <rootfrm.hxx>
+#include <fmtpdsc.hxx>
+#include <ndtxt.hxx>
 
 #include <boost/scoped_ptr.hpp>
 
@@ -2772,6 +2774,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
         const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
         bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
                                         rMaster.GetFooter().IsActive();
+        SwNodes *pTargetNodes = &pTargetShell->GetDoc()->GetNodes();
 
         // copy compatibility options
         lcl_CopyCompatibilityOptions( rSourceShell, *pTargetShell);
@@ -2860,6 +2863,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
 
             //#i63806# put the styles to the target document
             //if the source uses headers or footers each new copy need to copy a new page styles
+            SwPageDesc* pTargetPageDesc = NULL;
             if(bPageStylesWithHeaderFooter)
             {
                 //create a new pagestyle
@@ -2868,7 +2872,7 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 SwDoc* pTargetDoc = pTargetShell->GetDoc();
                 OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
                 pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
-                SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
+                pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
                 const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
 
                 if(pWorkPageDesc && pTargetPageDesc)
@@ -2911,7 +2915,29 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             if ( nDocNo <= MAX_DOC_DUMP )
                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
 #endif
-            pTargetShell->Paste( rWorkShell.GetDoc(), true );
+
+            SwNodeIndex fixupIdx( pTargetNodes->GetEndOfContent(), -1 );
+            pTargetShell->Paste( rWorkShell.GetDoc(), true, true );
+
+            if (bPageStylesWithHeaderFooter) {
+                // set the real page desc and update the number offset for the pasted document
+                fixupIdx += 2;
+                SwTxtNode *aTxtNd = fixupIdx.GetNode().GetTxtNode();
+                if ( aTxtNd ) {
+                    SfxPoolItem *pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
+                    SwFmtPageDesc *aDesc = dynamic_cast< SwFmtPageDesc* >( pNewItem );
+                    if ( aDesc ) {
+                        aDesc->SetNumOffset( nStartingPageNo );
+                        aDesc->RegisterToPageDesc( *pTargetPageDesc );
+                        aTxtNd->SetAttr( *aDesc );
+                    }
+                    delete pNewItem;
+                }
+
+                // delete the leading empty page from InsertPageBreak
+                fixupIdx -= 2;
+                pTargetNodes->Delete( fixupIdx, 2 );
+            }
 
             if ( para_added ) {
                 // Move cursor to the start or Delete will assert because
@@ -2921,12 +2947,9 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
                 pTargetNodes->Delete( aTargetIdx, 1 );
             }
 
-            //convert fields in page styles (header/footer - has to be done after the first document has been pasted
-            if(1 == nDocNo)
-            {
-                pTargetShell->CalcLayout();
-                pTargetShell->ConvertFieldsToText();
-            }
+            // #i72820# calculate layout to be able to find the correct page index
+            pTargetShell->CalcLayout();
+
 #ifdef DBG_UTIL
             if ( nDocNo <= MAX_DOC_DUMP )
                 lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
@@ -2935,8 +2958,6 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             //add the document info to the config item
             SwDocMergeInfo aMergeInfo;
             aMergeInfo.nStartPageInTarget = nPageCountBefore;
-            //#i72820# calculate layout to be able to find the correct page index
-            pTargetShell->CalcLayout();
             aMergeInfo.nEndPageInTarget = pTargetShell->GetPageCnt();
             aMergeInfo.nDBRow = nStartRow;
             rMMConfig.AddMergedDocument( aMergeInfo );
commit 39686c41434c871d37463ffdf89abb4f51af533c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jun 27 11:28:02 2014 +0200

    MM: fix workaround for single paragraph docs
    
    There is already a workaround for pasting a document with a single
    paragraph by appending a dummy empty paragraph to the working copy.
    
    This patch removes the dummy paragraph from the target document.
    
    Change-Id: I288d35264bf6f1a5f92c50d6a309e3bdd4ab5836

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 0ed706f..646a0a6 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2892,6 +2892,8 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
             }
             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
             OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
+            bool para_added = false;
+

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list