summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2014-06-28 01:41:17 +0200
committerBjörn Michaelsen <bjoern.michaelsen@canonical.com>2014-09-10 11:06:01 +0000
commitc808802e94eba48dc23d7fca133ed35c17feb163 (patch)
tree8faaf4dfaec9a046137d57eb084d0d74f9afca66
parent8e174eab91acec0f1578af4dac23be76dce700af (diff)
MM: introduce SwDoc::Append helper function
This drops all the specialized, workaround code from MM, introduced to use the SwFEShell::Paste function and additionally merges and renames SwDoc::Paste into SwDoc::Append. There is still a little common codepath, therefore this adds comments to always update both functions. Change-Id: I704b3ef3257dd977dac95e16e25049ff8ade97ed Reviewed-on: https://gerrit.libreoffice.org/10967 Reviewed-by: Björn Michaelsen <bjoern.michaelsen@canonical.com> Tested-by: Björn Michaelsen <bjoern.michaelsen@canonical.com>
-rw-r--r--sw/inc/doc.hxx4
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx4
-rw-r--r--sw/source/core/doc/docnew.cxx162
-rw-r--r--sw/source/core/frmedt/fecopy.cxx4
-rw-r--r--sw/source/uibase/dbui/dbmgr.cxx114
5 files changed, 158 insertions, 130 deletions
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index a1d6236cc9b5..f91432649da9 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -460,7 +460,6 @@ private:
OUString msDocAccTitle;
void InitTOXTypes();
- void Paste( const SwDoc& );
public:
enum DocumentType {
@@ -1646,7 +1645,10 @@ public:
::sw::MetaFieldManager & GetMetaFieldManager();
::sw::UndoManager & GetUndoManager();
::sw::UndoManager const& GetUndoManager() const;
+
SfxObjectShell* CreateCopy(bool bCallInitNew) const;
+ 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/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 4bbe194c6de6..f60fc5e445f0 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3138,8 +3138,10 @@ void DocumentContentOperationsManager::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/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 1a7e76e41c4d..ea9b136325c7 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -106,6 +106,7 @@
#include <DocumentExternalDataManager.hxx>
#include <unochart.hxx>
#include <fldbas.hxx>
+#include <wrtsh.hxx>
#include <cmdid.h>
@@ -900,7 +901,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();
}
@@ -912,14 +914,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
pRet->ReplaceStyles(*this);
- // copy content
- pRet->Paste( *this );
-
- 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 );
@@ -929,29 +924,64 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
return pRetShell;
}
-// copy document content - code from SwFEShell::Paste( SwDoc* )
-void SwDoc::Paste( const SwDoc& rSource )
+// appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
+void SwDoc::Append( const SwDoc& rSource, sal_uInt16 nStartPageNumber,
+ SwPageDesc* pTargetPageDesc, bool bDeletePrevious )
{
// GetEndOfExtras + 1 = StartOfContent == no content node!
// this ensures, that we have at least two nodes in the SwPaM.
// @see IDocumentContentOperations::CopyRange
SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 );
+ 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--;
+
+ // 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 );
- aCpyPam.SetMark();
- aCpyPam.Move( fnMoveForward, fnGoDoc );
this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
this->getIDocumentFieldsAccess().LockExpFlds();
{
+ // **
+ // ** refer to SwFEShell::Paste, if you change the following code **
+ // **
+
SwPosition& rInsPos = *aInsertPam.GetPoint();
- //find out if the clipboard document starts with a table
- bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
- SwPosition aInsertPosition( rInsPos );
{
SwNodeIndex aIndexBefore(rInsPos.nNode);
@@ -967,31 +997,88 @@ void SwDoc::Paste( const SwDoc& rSource )
aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
- // No need to update the rsid, as this is an empty doc
- }
+ // Update the rsid of each pasted text node
+ SwNodes &rDestNodes = GetNodes();
+ sal_uLong const nEndIdx = aPaM.End()->nNode.GetIndex();
- //TODO: Is this necessary here? SaveTblBoxCntnt( &rInsPos );
- if(/*bIncludingPageFrames && */bStartWithTable)
- {
- //remove the paragraph in front of the table
- SwPaM aPara(aInsertPosition);
- this->getIDocumentContentOperations().DelFullPara(aPara);
+ for (sal_uLong nIdx = aPaM.Start()->nNode.GetIndex();
+ nIdx <= nEndIdx; ++nIdx)
+ {
+ SwTxtNode *const pTxtNode = rDestNodes[nIdx]->GetTxtNode();
+ if ( pTxtNode )
+ UpdateParRsid( pTxtNode );
+ }
}
- //additionally copy page bound frames
- if( /*bIncludingPageFrames && */rSource.GetSpzFrmFmts()->size() )
+
{
- for ( sal_uInt16 i = 0; i < rSource.GetSpzFrmFmts()->size(); ++i )
- {
- const SwFrmFmt& rCpyFmt = *(*rSource.GetSpzFrmFmts())[i];
- SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
- if (FLY_AT_PAGE == aAnchor.GetAnchorId())
- {
- aAnchor.SetPageNum( aAnchor.GetPageNum() /*+ nStartPageNumber - */);
+ sal_uInt16 iDelNodes = 0;
+ SwNodeIndex aDelIdx( aFixupIdx );
+
+ // we just need to set the new page description and reset numbering
+ // this keeps all other settings as in the pasted document
+ if ( nStartPageNumber || pTargetPageDesc ) {
+ SfxPoolItem *pNewItem;
+ SwTxtNode *aTxtNd = 0;
+ SwFmt *pFmt = 0;
+
+ // find the first node allowed to contain a RES_PAGEDESC
+ while (1) {
+ aFixupIdx++;
+
+ SwNode &node = aFixupIdx.GetNode();
+ if ( node.IsTxtNode() ) {
+ // every document contains at least one text node!
+ aTxtNd = node.GetTxtNode();
+ pNewItem = aTxtNd->GetAttr( RES_PAGEDESC ).Clone();
+ break;
+ }
+ else if ( node.IsTableNode() ) {
+ pFmt = node.GetTableNode()->GetTable().GetFrmFmt();
+ pNewItem = pFmt->GetFmtAttr( RES_PAGEDESC ).Clone();
+ break;
}
- else
- continue;
- this->getIDocumentLayoutAccess().CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+ }
+
+ // just update the original instead of overwriting
+ SwFmtPageDesc *aDesc = static_cast< SwFmtPageDesc* >( pNewItem );
+ if ( nStartPageNumber )
+ aDesc->SetNumOffset( nStartPageNumber );
+ if ( pTargetPageDesc )
+ aDesc->RegisterToPageDesc( *pTargetPageDesc );
+ if ( aTxtNd )
+ aTxtNd->SetAttr( *aDesc );
+ else
+ pFmt->SetFmtAttr( *aDesc );
+ 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 );
+ }
+ }
+
+ // finally copy page bound frames
+ const SwFrmFmts *pSpzFrmFmts = rSource.GetSpzFrmFmts();
+ for ( sal_uInt16 i = 0; i < pSpzFrmFmts->size(); ++i )
+ {
+ const SwFrmFmt& rCpyFmt = *(*pSpzFrmFmts)[i];
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if (FLY_AT_PAGE != aAnchor.GetAnchorId())
+ continue;
+ if ( nPhysPageNumber )
+ aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber );
+ this->getIDocumentLayoutAccess().CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
}
}
@@ -999,6 +1086,9 @@ void SwDoc::Paste( const SwDoc& rSource )
getIDocumentFieldsAccess().UnlockExpFlds();
getIDocumentFieldsAccess().UpdateFlds(NULL, false);
+
+ if ( pTargetShell )
+ pTargetShell->EndAllAction();
}
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 e3612e40beba..3669a5902734 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1028,6 +1028,10 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, bool bIncludingPageFrames )
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 20bcefb26d46..7b013a7cf678 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -885,7 +885,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
// in case of creating a single resulting file this has to be created here
SwWrtShell* pTargetShell = 0;
SwDoc* pTargetDoc = 0;
- SwNodes* pTargetNodes = 0;
// the shell will be explicitly closed at the end of the method, but it is
// still more safe to use SfxObjectShellLock here
@@ -897,6 +896,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
OUString sStartingPageDesc;
sal_uInt16 nStartingPageNo = 0;
bool bPageStylesWithHeaderFooter = false;
+
if(bAsSingleFile || rMergeDescriptor.bCreateSingleFile)
{
// create a target docshell to put the merged document into
@@ -910,7 +910,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
pTargetShell = pTargetView->GetWrtShellPtr();
pTargetDoc = pTargetShell->GetDoc();
- pTargetNodes = &pTargetDoc->GetNodes();
+
//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
@@ -1050,66 +1050,32 @@ 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
- SwPageDesc* pSourcePageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
- pTargetDoc->MakePageDesc( sNewPageDescName );
- SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
- if(pSourcePageDesc && pTargetPageDesc)
+ pTargetPageDesc = pTargetDoc->MakePageDesc( 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");
+ pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
- //#i51359# add a second paragraph in case there's only one
- bool para_added = false;
- {
- SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
- SwPosition aTestPos( aIdx );
- SwCursor aTestCrsr(aTestPos,0,false);
- if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
- {
- //append a paragraph
- pWorkDoc->getIDocumentContentOperations().AppendTxtNode( aTestPos );
- para_added = true;
- }
- }
- pTargetShell->Paste( rWorkShell.GetDoc(), true );
-
- 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 );
- }
+ 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();
- }
+ // #i72820# calculate layout to be able to find the correct page index
+ pTargetShell->CalcLayout();
}
else
{
@@ -2775,7 +2741,8 @@ sal_Int32 SwDBManager::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr();
SwDoc* pTargetDoc = pTargetShell->GetDoc();
- SwNodes* pTargetNodes = &pTargetDoc->GetNodes();
+
+ pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), true );
// #i63806#
const SwPageDesc* pSourcePageDesc = rSourceShell.FindPageDescByName( sStartingPageDesc );
@@ -2852,21 +2819,16 @@ 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
+ 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
-
OUString sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
- pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
- SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
+ pTargetPageDesc = pTargetDoc->MakePageDesc( sNewPageDescName );
const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
if(pWorkPageDesc && pTargetPageDesc)
@@ -2876,50 +2838,20 @@ 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
- pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
+ pTargetPageDesc = pTargetShell->FindPageDescByName( 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->getIDocumentContentOperations().AppendTxtNode( aTestPos );
- para_added = true;
- }
- }
#ifdef DBG_UTIL
if ( nDocNo <= MAX_DOC_DUMP )
lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
#endif
- pTargetShell->Paste( rWorkShell.GetDoc(), true );
-
- 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 );
- }
+ 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();
- }
+ // #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" );
@@ -2928,8 +2860,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 );