[Libreoffice-commits] core.git: 11 commits - sw/inc sw/qa sw/source

Luboš Luňák l.lunak at collabora.com
Thu Nov 6 07:55:51 PST 2014


 sw/inc/doc.hxx                                           |    4 
 sw/qa/extras/inc/swmodeltestbase.hxx                     |   85 ++++++---
 sw/qa/extras/mailmerge/data/10-testing-addresses.ods     |binary
 sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt |binary
 sw/qa/extras/mailmerge/data/simple-mail-merge.odt        |binary
 sw/qa/extras/mailmerge/mailmerge.cxx                     |  138 +++++++++++++--
 sw/source/core/doc/docnew.cxx                            |   34 +--
 sw/source/ui/dbui/mmoutputpage.cxx                       |   55 +++++
 sw/source/ui/dbui/mmoutputpage.hxx                       |    4 
 sw/source/uibase/dbui/dbmgr.cxx                          |   24 +-
 sw/source/uibase/inc/mmconfigitem.hxx                    |    4 
 11 files changed, 271 insertions(+), 77 deletions(-)

New commits:
commit 9e05e45452bfc98c39f589b3f3b90c6596a638c9
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Thu Nov 6 16:51:33 2014 +0100

    unittest verifying that mail merge correctly sets up marks for sub-documents
    
    I.e. the UNO bookmarks that are used for marking where each generated document
    starts inside the one large single document.
    
    Change-Id: I8069a3110cacd34b25aff6739ab248f490c3fa6a

diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index efb356c..15a4ea0 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -33,7 +33,7 @@
 
 class MMTest : public SwModelTestBase
 {
-    public:
+public:
         MMTest() : SwModelTestBase("/sw/qa/extras/mailmerge/data/", "writer8") {}
     /**
      * Helper func used by each unit test to test the 'mail merge' code.
@@ -64,6 +64,9 @@ class MMTest : public SwModelTestBase
         nCurOutputType = 0;
     }
 
+protected:
+    // Returns page number of the first page of a MM document inside the large MM document (used in the SHELL case).
+    int documentStartPageNumber( int document ) const;
 };
 
 #define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass) \
@@ -91,6 +94,30 @@ class MMTest : public SwModelTestBase
 #define DECLARE_FILE_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
     DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest)
 
+int MMTest::documentStartPageNumber( int document ) const
+{   // See SwMailMergeOutputPage::documentStartPageNumber() .
+    SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
+    CPPUNIT_ASSERT(pTxtDoc);
+    SwWrtShell* shell = pTxtDoc->GetDocShell()->GetWrtShell();
+    IDocumentMarkAccess* marks = shell->GetDoc()->getIDocumentMarkAccess();
+    // Unfortunately, the pages are marked using UNO bookmarks, which have internals names, so they cannot be referred to by their names.
+    // Assume that there are no other UNO bookmarks than the ones used by mail merge, and that they are in the sorted order.
+    IDocumentMarkAccess::const_iterator_t mark;
+    int pos = 0;
+    for( mark = marks->getAllMarksBegin(); mark != marks->getAllMarksEnd() && pos < document; ++mark )
+    {
+        if( IDocumentMarkAccess::GetType( **mark ) == IDocumentMarkAccess::UNO_BOOKMARK )
+            ++pos;
+    }
+    CPPUNIT_ASSERT( pos == document );
+    sal_uInt16 page, dummy;
+    shell->Push();
+    shell->GotoMark( mark->get());
+    shell->GetPageNum( page, dummy );
+    shell->Pop(false);
+    return page;
+}
+
 DECLARE_SHELL_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1")
 {
     executeMailMerge();
@@ -190,6 +217,39 @@ DECLARE_FILE_MAILMERGE_TEST(test2Pages, "simple-mail-merge-2pages.odt", "10-test
     }
 }
 
+DECLARE_SHELL_MAILMERGE_TEST(testPageBoundariesSimpleMailMerge, "simple-mail-merge.odt", "10-testing-addresses.ods", "testing-addresses")
+{
+    // This is like the test above, but this one uses the create-single-document-containing-everything-generated approach,
+    // and verifies that boundaries of the generated sub-documents are correct inside that document.
+    // These boundaries are done using "SwMailMergeOutputPage::documentStartPageNumber<number>" UNO bookmarks (see also
+    // SwMailMergeOutputPage::documentStartPageNumber() ).
+    executeMailMerge();
+    // Here getPages() works on the source document, so get pages of the resulting one.
+    SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
+    CPPUNIT_ASSERT(pTxtDoc);
+    CPPUNIT_ASSERT_EQUAL( sal_uInt16( 19 ), pTxtDoc->GetDocShell()->GetWrtShell()->GetPhyPageNum()); // 10 pages, but each sub-document starts on odd page number
+    for( int doc = 0;
+         doc < 10;
+         ++doc )
+    {
+        CPPUNIT_ASSERT_EQUAL( doc * 2 + 1, documentStartPageNumber( doc ));
+    }
+}
+
+DECLARE_SHELL_MAILMERGE_TEST(testPageBoundaries2Pages, "simple-mail-merge-2pages.odt", "10-testing-addresses.ods", "testing-addresses")
+{
+    executeMailMerge();
+    SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
+    CPPUNIT_ASSERT(pTxtDoc);
+    CPPUNIT_ASSERT_EQUAL( sal_uInt16( 20 ), pTxtDoc->GetDocShell()->GetWrtShell()->GetPhyPageNum()); // 20 pages, each sub-document starts on odd page number
+    for( int doc = 0;
+         doc < 10;
+         ++doc )
+    {
+        CPPUNIT_ASSERT_EQUAL( doc * 2 + 1, documentStartPageNumber( doc ));
+    }
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit b1263c09c9f7ece4f4173b2738e91dcc0b580827
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Thu Nov 6 16:43:28 2014 +0100

    name of mailmerge marks is actually irrelevant
    
    UNO bookmarks have internals names and ignore this
    
    Change-Id: I37baa4c9bcf9cec37f91e3b1d0fb2fad322ceda8

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 2d1ce30..142faf4 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1141,7 +1141,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             if (bMergeShell)
                             {
                                 SwDocMergeInfo aMergeInfo;
-                                aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "MailMergeInternalStart" + OUString::number( nStartRow ),
+                                // Name of the mark is actually irrelevant, UNO bookmarks have internals names.
+                                aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "",
                                     IDocumentMarkAccess::UNO_BOOKMARK );
                                 aMergeInfo.nDBRow = nStartRow;
                                 rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
commit 5f7bdec8207672c68c34dbbd833bf6b534cf182f
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 20:46:49 2014 +0100

    unit test to verify basic mail merge layout for 2 pages
    
    Change-Id: I2172d0185a2481700ffe152e58ebd5bd9c6a4fab

diff --git a/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt b/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt
new file mode 100644
index 0000000..c0a86ae
Binary files /dev/null and b/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt differ
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 78573b3..efb356c 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -164,6 +164,32 @@ DECLARE_FILE_MAILMERGE_TEST(testSimpleMailMerge, "simple-mail-merge.odt", "10-te
     }
 }
 
+DECLARE_FILE_MAILMERGE_TEST(test2Pages, "simple-mail-merge-2pages.odt", "10-testing-addresses.ods", "testing-addresses")
+{
+    executeMailMerge();
+    for( int doc = 0;
+         doc < 10;
+         ++doc )
+    {
+        loadMailMergeDocument( doc );
+        OUString lastname = "lastname" + OUString::number( doc + 1 );
+        OUString firstname = "firstname" + OUString::number( doc + 1 );
+        CPPUNIT_ASSERT_EQUAL( 2, getPages());
+        CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), getRun( getParagraph( 1 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( lastname, getRun( getParagraph( 2 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( OUString( "Another fixed text." ), getRun( getParagraph( 3 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 4 ), 1 )->getString()); // empty para at the end of page 1
+        CPPUNIT_ASSERT_EQUAL( OUString( "Second page." ), getRun( getParagraph( 5 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( firstname, getRun( getParagraph( 6 ), 1 )->getString());
+        // Also verify the layout.
+        CPPUNIT_ASSERT_EQUAL( lastname, parseDump("/root/page[1]/body/txt[2]/Special", "rText"));
+        CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), parseDump("/root/page[1]/body/txt[1]", ""));
+        CPPUNIT_ASSERT_EQUAL( OUString( "" ), parseDump("/root/page[1]/body/txt[4]", ""));
+        CPPUNIT_ASSERT_EQUAL( OUString( "Second page." ), parseDump("/root/page[2]/body/txt[1]", ""));
+        CPPUNIT_ASSERT_EQUAL( firstname, parseDump("/root/page[2]/body/txt[2]/Special", "rText"));
+    }
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 3b72f55247a5d9b62490b66900d91f797674b50d
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 20:26:25 2014 +0100

    properly discard dumped layout on test document (re)loads
    
    Change-Id: I8673810e8c04cd128a691ee1c1e8c4731108b605

diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx
index dd6a481..413d016 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -362,6 +362,15 @@ private:
         xmlFreeTextWriter(pXmlWriter);
     }
 
+    void discardDumpedLayout()
+    {
+        if (mpXmlBuffer)
+        {
+            xmlBufferFree(mpXmlBuffer);
+            mpXmlBuffer = 0;
+        }
+    }
+
     void calcLayout()
     {
         SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
@@ -610,6 +619,7 @@ protected:
         std::cout << pName << ",";
         mnStartTime = osl_getGlobalTimer();
         mxComponent = loadFromDesktop(getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.text.TextDocument");
+        discardDumpedLayout();
         if (mustCalcLayoutOf(pName))
             calcLayout();
     }
@@ -629,6 +639,7 @@ protected:
         mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + name, "com.sun.star.text.TextDocument");
         CPPUNIT_ASSERT( mxComponent.is());
         OString name2 = OUStringToOString( name, RTL_TEXTENCODING_UTF8 );
+        discardDumpedLayout();
         if (mustCalcLayoutOf(name2.getStr()))
             calcLayout();
     }
@@ -659,12 +670,7 @@ protected:
                 validate(maTempFile.GetFileName(), test::ODF);
             }
         }
-
-        if (mpXmlBuffer)
-        {
-            xmlBufferFree(mpXmlBuffer);
-            mpXmlBuffer = 0;
-        }
+        discardDumpedLayout();
         if (mustCalcLayoutOf(filename))
             calcLayout();
     }
@@ -685,11 +691,7 @@ protected:
     {
         sal_uInt32 nEndTime = osl_getGlobalTimer();
         std::cout << (nEndTime - mnStartTime) << std::endl;
-        if (mpXmlBuffer)
-        {
-            xmlBufferFree(mpXmlBuffer);
-            mpXmlBuffer = 0;
-        }
+        discardDumpedLayout();
     }
 
     /// Get page count.
commit 0d349a49871301506c3a714c95bbe309bbd7eb1d
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 20:21:35 2014 +0100

    make parseDump() properly handle xml node content
    
    Change-Id: Ibb8859908c8e73377e1ee20b041b9ae76955d076

diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx
index f4c6841..dd6a481 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -430,7 +430,7 @@ protected:
         if (aAttribute.getLength())
             aRet = OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr())));
         else
-            aRet = OUString::createFromAscii((const char*)XML_GET_CONTENT(pXmlNode));
+            aRet = OUString::createFromAscii((const char*)xmlNodeGetContent(pXmlNode));
 
         xmlFreeDoc(pXmlDoc);
 
commit 53eeff46cd98e1fb497023f4fe30e9421c189127
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 19:27:19 2014 +0100

    basic test of mail merge working
    
    Change-Id: Ia72d1b2827bfb38ab39d7d0df04908874d25e124

diff --git a/sw/qa/extras/mailmerge/data/10-testing-addresses.ods b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods
new file mode 100644
index 0000000..33b82e6
Binary files /dev/null and b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods differ
diff --git a/sw/qa/extras/mailmerge/data/simple-mail-merge.odt b/sw/qa/extras/mailmerge/data/simple-mail-merge.odt
new file mode 100644
index 0000000..34637d4
Binary files /dev/null and b/sw/qa/extras/mailmerge/data/simple-mail-merge.odt differ
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 4ee1503..78573b3 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -149,6 +149,21 @@ DECLARE_FILE_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-c
     CPPUNIT_ASSERT_EQUAL( OUString( "#000000" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]/style:graphic-properties", "stroke-color"));
 }
 
+DECLARE_FILE_MAILMERGE_TEST(testSimpleMailMerge, "simple-mail-merge.odt", "10-testing-addresses.ods", "testing-addresses")
+{
+    executeMailMerge();
+    for( int doc = 0;
+         doc < 10;
+         ++doc )
+    {
+        loadMailMergeDocument( doc );
+        CPPUNIT_ASSERT_EQUAL( 1, getPages());
+        CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), getRun( getParagraph( 1 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( OUString( "lastname" + OUString::number( doc + 1 )), getRun( getParagraph( 2 ), 1 )->getString());
+        CPPUNIT_ASSERT_EQUAL( OUString( "Another fixed text." ), getRun( getParagraph( 3 ), 1 )->getString());
+    }
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 74720747d9c93b6d54dc7550a05b90b9b7d5a8a8
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 19:25:04 2014 +0100

    do not register MM unittest databases with a prefix
    
    Since that makes SwDBManager::IsDataSourceOpen() return false because
    of different data sources (than the one the document was tested with manually),
    which prevents DocumentFieldsManager::UpdateExpFlds() from updating fields
    properly.
    
    Change-Id: I66f5f79d9fd39204eabb247aa92ec11acef56903

diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx
index da7921f..f4c6841 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -801,13 +801,13 @@ protected:
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("css3t"), BAD_CAST("http://www.w3.org/TR/css3-text/"));
     }
 
-    virtual OUString registerDBsource( const OUString &aURI, const OUString &aPrefix, const OUString &aWorkDir )
+    virtual OUString registerDBsource( const OUString &aURI, const OUString &aWorkDir )
     {
         OUString aDBName;
         DBuriMap::const_iterator pos = aDBuriMap.find( aURI );
         if (pos == aDBuriMap.end())
         {
-            aDBName = SwDBManager::LoadAndRegisterDataSource( aURI, &aPrefix, &aWorkDir );
+            aDBName = SwDBManager::LoadAndRegisterDataSource( aURI, NULL, &aWorkDir );
             aDBuriMap.insert( std::pair< OUString, OUString >( aURI, aDBName ) );
             std::cout << "New datasource name: '" << aDBName << "'" << std::endl;
         }
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index d278db1..4ee1503 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -50,12 +50,11 @@ class MMTest : public SwModelTestBase
         preTest(filename);
         load(mpTestDocumentPath, filename);
 
-        const OUString aPrefix( "LOMM_" );
         utl::TempFile aTempDir(nullptr, true);
         const OUString aWorkDir = aTempDir.GetURL();
         const OUString aURI( getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) );
-        OUString aDBName = registerDBsource( aURI, aPrefix, aWorkDir );
-        initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir, file );
+        OUString aDBName = registerDBsource( aURI, aWorkDir );
+        initMailMergeJobAndArgs( filename, tablename, aDBName, "LOMM_", aWorkDir, file );
 
         postTest(filename);
         verify();
commit b4bc6521759103a5a79819a082e7413737212a76
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Nov 5 14:19:23 2014 +0100

    make it possible to check mailmerge output files in unittests
    
    Change-Id: Ifa54445c8f46bb2ed5539870c5fce1a2e62beef7

diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx
index b642abc..da7921f 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -182,6 +182,8 @@ protected:
     utl::TempFile maTempFile;
     bool mbExported; ///< Does maTempFile already contain something useful?
     sal_Int16 nCurOutputType;
+    OUString mailMergeOutputURL;
+    OUString mailMergeOutputPrefix;
 
 protected:
     virtual OUString getTestName() { return OUString(); }
@@ -612,6 +614,25 @@ protected:
             calcLayout();
     }
 
+    /**
+     Loads number-th document from mail merge. Requires file output from mail merge.
+    */
+    void loadMailMergeDocument( int number )
+    {
+        assert( nCurOutputType == text::MailMergeType::FILE );
+        if (mxComponent.is())
+            mxComponent->dispose();
+        OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt";
+        // Output name early, so in the case of a hang, the name of the hanging input file is visible.
+        std::cout << name << ",";
+        mnStartTime = osl_getGlobalTimer();
+        mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + name, "com.sun.star.text.TextDocument");
+        CPPUNIT_ASSERT( mxComponent.is());
+        OString name2 = OUStringToOString( name, RTL_TEXTENCODING_UTF8 );
+        if (mustCalcLayoutOf(name2.getStr()))
+            calcLayout();
+    }
+
     void reload(const char* pFilter, const char* filename)
     {
         uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
@@ -692,8 +713,25 @@ protected:
         if (!mbExported)
             return 0;
 
+        return parseExportInternal( maTempFile.GetURL(), rStreamName );
+    }
+
+    /**
+     * Like parseExport(), but for given mail merge document.
+     */
+    xmlDocPtr parseMailMergeExport(int number, const OUString& rStreamName = OUString("word/document.xml"))
+    {
+        if (nCurOutputType != text::MailMergeType::FILE)
+            return 0;
+
+        OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt";
+        return parseExportInternal( mailMergeOutputURL + "/" + name, rStreamName );
+    }
+
+    xmlDocPtr parseExportInternal( const OUString& url, const OUString& rStreamName )
+    {
         // Read the XML stream we're interested in.
-        uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
+        uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), url);
         uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(rStreamName), uno::UNO_QUERY);
         boost::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
 
@@ -783,7 +821,7 @@ protected:
     }
 
     virtual void initMailMergeJobAndArgs( const char* filename, const char* tablename, const OUString &aDBName,
-                                          const OUString &aPrefix, const OUString &aWorkDir )
+                                          const OUString &aPrefix, const OUString &aWorkDir, bool file )
     {
         uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW );
         mxJob.set( xJob );
@@ -793,7 +831,7 @@ protected:
         mSeqMailMergeArgs.realloc( seq_id );
 
         seq_id = 0;
-        mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( text::MailMergeType::SHELL ) );
+        mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) );
         mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any(
                                         ( OUString(getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) );
         mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) );
@@ -810,8 +848,6 @@ protected:
     {
         uno::Any res = mxJob->execute( mSeqMailMergeArgs );
 
-        OUString aCurOutputURL;
-        OUString aCurFileNamePrefix;
         const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray();
         bool bOk = true;
         sal_Int32 nArgs = mSeqMailMergeArgs.getLength();
@@ -822,9 +858,9 @@ protected:
 
             // all error checking was already done by the MM job execution
             if (rName == UNO_NAME_OUTPUT_URL)
-                bOk &= rValue >>= aCurOutputURL;
+                bOk &= rValue >>= mailMergeOutputURL;
             else if (rName == UNO_NAME_FILE_NAME_PREFIX)
-                bOk &= rValue >>= aCurFileNamePrefix;
+                bOk &= rValue >>= mailMergeOutputPrefix;
             else if (rName == UNO_NAME_OUTPUT_TYPE)
                 bOk &= rValue >>= nCurOutputType;
         }
@@ -839,10 +875,7 @@ protected:
         else
         {
             CPPUNIT_ASSERT(res == true);
-            mxMMComponent = loadFromDesktop( aCurOutputURL + "/" + aCurFileNamePrefix + "0.odt",
-                                             "com.sun.star.text.TextDocument");
-            CPPUNIT_ASSERT(mxMMComponent.is());
-            calcLayout();
+            loadMailMergeDocument( 0 );
         }
     }
 };
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 1260d69..d278db1 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -44,7 +44,7 @@ class MMTest : public SwModelTestBase
      * The 'verify' method actually has to execute the mail merge by
      * calling executeMailMerge() after modifying the job arguments.
      */
-    void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename = 0)
+    void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename, bool file)
     {
         header();
         preTest(filename);
@@ -55,18 +55,19 @@ class MMTest : public SwModelTestBase
         const OUString aWorkDir = aTempDir.GetURL();
         const OUString aURI( getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) );
         OUString aDBName = registerDBsource( aURI, aPrefix, aWorkDir );
-        initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir );
+        initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir, file );
 
         postTest(filename);
         verify();
         finish();
 
         ::utl::removeTree(aWorkDir);
+        nCurOutputType = 0;
     }
 
 };
 
-#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, BaseClass) \
+#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass) \
     class TestName : public BaseClass { \
     protected: \
         virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \
@@ -76,17 +77,22 @@ class MMTest : public SwModelTestBase
         CPPUNIT_TEST_SUITE_END(); \
     \
         void MailMerge() { \
-            executeMailMergeTest(filename, datasource, tablename); \
+            executeMailMergeTest(filename, datasource, tablename, file); \
         } \
         void verify() SAL_OVERRIDE; \
     }; \
     CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
     void TestName::verify()
 
-#define DECLARE_DFLT_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
-    DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, MMTest)
+// Will generate the resulting document in mxMMDocument.
+#define DECLARE_SHELL_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
+    DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest)
 
-DECLARE_DFLT_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1")
+// Will generate documents as files, use loadMailMergeDocument().
+#define DECLARE_FILE_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
+    DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest)
+
+DECLARE_SHELL_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1")
 {
     executeMailMerge();
 
@@ -117,19 +123,19 @@ DECLARE_DFLT_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-
     }
 }
 
-DECLARE_DFLT_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-color.ott", "one-empty-address.ods", "one-empty-address")
+DECLARE_FILE_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-color.ott", "one-empty-address.ods", "one-empty-address")
 {
     executeMailMerge();
     // The document was created by LO version which didn't write out the default value for line color
     // (see XMLGraphicsDefaultStyle::SetDefaults()).
-    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxMMComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
     uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
     uno::Reference<beans::XPropertySet> xPropertySet(xDraws->getByIndex(0), uno::UNO_QUERY);
     // Lines do not have a line color.
     CPPUNIT_ASSERT( !xPropertySet->getPropertySetInfo()->hasPropertyByName( "LineColor" ));
-    SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
+    SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
     CPPUNIT_ASSERT(pTxtDoc);
-    uno::Reference< lang::XMultiServiceFactory > xFact( mxMMComponent, uno::UNO_QUERY );
+    uno::Reference< lang::XMultiServiceFactory > xFact( mxComponent, uno::UNO_QUERY );
     uno::Reference< beans::XPropertySet > xDefaults( xFact->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY );
     CPPUNIT_ASSERT( xDefaults.is());
     uno::Reference< beans::XPropertySetInfo > xInfo( xDefaults->getPropertySetInfo());
@@ -138,6 +144,10 @@ DECLARE_DFLT_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-c
     xDefaults->getPropertyValue( "LineColor" ) >>= lineColor;
     // And the default value is black (wasn't copied properly by mailmerge).
     CPPUNIT_ASSERT_EQUAL( COL_BLACK, lineColor );
+    // And check that the resulting file has the proper default.
+    xmlDocPtr pXmlDoc = parseMailMergeExport( 0, "styles.xml" );
+    CPPUNIT_ASSERT_EQUAL( OUString( "graphic" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]", "family"));
+    CPPUNIT_ASSERT_EQUAL( OUString( "#000000" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]/style:graphic-properties", "stroke-color"));
 }
 
 #endif
commit f373aa0be0a2150c05de5b215f18ed8f0f333e83
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Oct 22 13:20:49 2014 +0200

    do not repeatedly relayout mailmerge document after each change
    
    When mailmerge uses a single document for all the generated documents, doing
    a layout of this increasingly large document after every generated document
    addition was getting slower and slower (no wonder). My recent changes should
    have removed all needs for any layout in progress, so it should be enough
    to just once calculate the final layout. The final layout still appears to be
    needed, leaving it as it is to get layout done on the fly puts e.g. 2-page
    documents on wrong starting page (maybe just invalidating something would fix
    that).
    Debug build shows warnings from vdraw.cxx about moving anchor from an invalid
    page because of broken layouting, but those were there already before, so I
    assume those are not really significant (or at least made worse by this commit).
    
    Change-Id: I62601ad6dccaa008783d1ce34c9e4f66f9621a56

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 4a07408..2d1ce30 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1135,8 +1135,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
                             SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
                                 nStartingPageNo, pTargetPageDesc, nDocNo == 1, targetDocPageCount);
-                            // #i72820# calculate layout to be able to find the correct page index
-                            pTargetShell->CalcLayout();
                             targetDocPageCount += rWorkShell.GetPageCnt();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
@@ -1288,6 +1286,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             // Unfreeze target document layouts and correct all PageDescs.
             if(rMergeDescriptor.bCreateSingleFile)
             {
+                pTargetShell->CalcLayout();
                 std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts();
                 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),
                     ::std::bind2nd(::std::mem_fun(&SwRootFrm::FreezeLayout), false));
commit ae5afe9bcebdd220a457829d47882fe8a0cf69fd
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Mon Oct 20 22:05:51 2014 +0200

    compute page offset for mailmerge based on source document rather than target
    
    This removes another need for doing repeated and expensive layouts of the target
    document.
    
    Change-Id: Id78bc3ccc71c17e42f858dc9660866b9c94dea3a

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 8a382e1..c8b88c2 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1660,7 +1660,7 @@ public:
 
     SfxObjectShell* CreateCopy(bool bCallInitNew) const;
     SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber,
-                 SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false );
+                 SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false, int physicalPageOffset = 0 );
 
     /**
      * 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 066f625..70bda8c 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -932,7 +932,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
 // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
 SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
-            SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious)
+            SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious, int pageOffset)
 {
     // GetEndOfExtras + 1 = StartOfContent == no content node!
     // @see IDocumentContentOperations::CopyRange
@@ -973,7 +973,6 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
 #endif
 
     SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell();
-    sal_uInt16 nPhysPageNumber = 0;
     if ( pTargetShell ) {
 #ifdef DBG_UTIL
         SAL_INFO( "sw.docappend", "Has target write shell" );
@@ -985,18 +984,6 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
             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++;
-#ifdef DBG_UTIL
-    SAL_INFO( "sw.docappend", "PPNo " << nPhysPageNumber );
-#endif
     }
 #ifdef DBG_UTIL
     SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
@@ -1154,10 +1141,10 @@ else
                 continue;
 #ifdef DBG_UTIL
     SAL_INFO( "sw.docappend", "PaAn: " << aAnchor.GetPageNum()
-                              << " => " << aAnchor.GetPageNum() + nPhysPageNumber );
+                              << " => " << aAnchor.GetPageNum() + pageOffset );
 #endif
-            if ( nPhysPageNumber )
-                aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber );
+            if ( pageOffset != 0 )
+                aAnchor.SetPageNum( aAnchor.GetPageNum() + pageOffset );
             this->getIDocumentLayoutAccess().CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
         }
     }
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index c6f48fe..4a07408 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -979,6 +979,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             sal_Int32 nDocNo = 1;
             sal_Int32 nDocCount = 0;
+            // For single file mode, the number of pages in the target document so far, which is used
+            // by AppendDoc() to adjust position of page-bound objects. Getting this information directly
+            // from the target doc would require repeated layouts of the doc, which is expensive, but
+            // it can be manually computed from the source documents (for which we do layouts, so the page
+            // count is known, and there is a blank page between each of them in the target document).
+            int targetDocPageCount = 0;
             if( !IsMergeSilent() && bMergeShell &&
                     lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) )
                 static_cast<CreateMonitor*>( pProgressDlg )->SetTotalCount( nDocCount );
@@ -1125,10 +1131,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
+                            if( targetDocPageCount % 2 == 1 )
+                                ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
                             SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
-                                nStartingPageNo, pTargetPageDesc, nDocNo == 1);
+                                nStartingPageNo, pTargetPageDesc, nDocNo == 1, targetDocPageCount);
                             // #i72820# calculate layout to be able to find the correct page index
                             pTargetShell->CalcLayout();
+                            targetDocPageCount += rWorkShell.GetPageCnt();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
                             if (bMergeShell)
commit a305a2c91420652db450b7f8edd140e1d69f42cf
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Mon Oct 20 15:13:03 2014 +0200

    use bookmarks to mark mailmerge parts in a mailmerge document (fdo#80823)
    
    Instead of page numbers, which
    - was somewhat fragile (and broken, as it was actually off-by-one)
    - required repeated re-layout of the increasingly large document, making
      mailmerge awfully slow. The re-layout is not removed by this commit, as
      it needs further checking whether it can be removed.
    See the bugreport for details.
    
    Change-Id: Ib09bd5f5a6a549c3d38ca40b0f32c0d2831fdd4c

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index eb1a240..8a382e1 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1659,7 +1659,7 @@ public:
     ::sw::UndoManager const& GetUndoManager() const;
 
     SfxObjectShell* CreateCopy(bool bCallInitNew) const;
-    void AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber,
+    SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber,
                  SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false );
 
     /**
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index a8405d5..066f625 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -931,7 +931,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 }
 
 // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
-void SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
+SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
             SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious)
 {
     // GetEndOfExtras + 1 = StartOfContent == no content node!
@@ -1020,6 +1020,9 @@ void SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
     this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
     this->getIDocumentFieldsAccess().LockExpFlds();
 
+    // Position where the appended doc starts. Will be filled in later (uses GetEndOfContent() because SwNodeIndex has no default ctor).
+    SwNodeIndex aStartAppendIndex( GetNodes().GetEndOfContent() );
+
     {
         // **
         // ** refer to SwFEShell::Paste, if you change the following code **
@@ -1132,6 +1135,12 @@ else
                               << "  EOE: " << GetNodes().GetEndOfExtras().GetIndex() );
 #endif
                 GetNodes().Delete( aDelIdx, iDelNodes );
+                aStartAppendIndex = aFixupIdx;
+            }
+            else
+            {
+                aStartAppendIndex = aFixupIdx;
+                ++aStartAppendIndex;
             }
         }
 
@@ -1160,6 +1169,8 @@ else
 
     if ( pTargetShell )
         pTargetShell->EndAllAction();
+
+    return aStartAppendIndex;
 }
 
 sal_uInt16 SwTxtFmtColls::GetPos(const SwTxtFmtColl* p) const
diff --git a/sw/source/ui/dbui/mmoutputpage.cxx b/sw/source/ui/dbui/mmoutputpage.cxx
index 17f3b7e..0034007 100644
--- a/sw/source/ui/dbui/mmoutputpage.cxx
+++ b/sw/source/ui/dbui/mmoutputpage.cxx
@@ -553,6 +553,50 @@ IMPL_LINK_NOARG(SwMailMergeOutputPage, SaveCancelHdl_Impl)
     return 0;
 }
 
+int SwMailMergeOutputPage::documentStartPageNumber( int document ) const
+{
+    SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
+    SwView* pTargetView = rConfigItem.GetTargetView();
+    assert( pTargetView );
+    SwCrsrShell& shell = pTargetView->GetWrtShell();
+    const SwDocMergeInfo& info = rConfigItem.GetDocumentMergeInfo( document );
+    sal_uInt16 page, dummy;
+    shell.Push();
+    shell.GotoMark( info.startPageInTarget );
+    shell.GetPageNum( page, dummy );
+    shell.Pop(false);
+    return page;
+}
+
+int SwMailMergeOutputPage::documentEndPageNumber( int document ) const
+{
+    SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
+    SwView* pTargetView = rConfigItem.GetTargetView();
+    assert( pTargetView );
+    SwWrtShell& shell = pTargetView->GetWrtShell();
+    if( document < int( rConfigItem.GetMergedDocumentCount()) - 1 )
+    {
+        // Go to the page before the starting page of the next merged document.
+        const SwDocMergeInfo& info = rConfigItem.GetDocumentMergeInfo( document + 1 );
+        sal_uInt16 page, dummy;
+        shell.Push();
+        shell.GotoMark( info.startPageInTarget );
+        shell.EndPrvPg();
+        shell.GetPageNum( page, dummy );
+        shell.Pop(false);
+        return page;
+    }
+    else
+    {   // This is the last merged document, so it ends on the page at which the document ends.
+        sal_uInt16 page, dummy;
+        shell.Push();
+        shell.SttEndDoc( false ); // go to doc end
+        shell.GetPageNum( page, dummy );
+        shell.Pop(false);
+        return page;
+    }
+}
+
 IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton)
 {
     SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem();
@@ -655,7 +699,6 @@ IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton)
 
         for(sal_uInt32 nDoc = nBegin; nDoc < nEnd && !m_bCancelSaving; ++nDoc)
         {
-            SwDocMergeInfo& rInfo = rConfigItem.GetDocumentMergeInfo(nDoc);
             INetURLObject aURL(sPath);
             OUString sExtension = aURL.getExtension();
             if (sExtension.isEmpty())
@@ -686,7 +729,7 @@ IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton)
             pTempView->GetDocShell()->GetDoc()->ReplaceDocumentProperties( *pTargetView->GetDocShell()->GetDoc(), true );
 
             pTargetView->GetWrtShell().PastePages(pTempView->GetWrtShell(),
-                    (sal_uInt16)rInfo.nStartPageInTarget, (sal_uInt16)rInfo.nEndPageInTarget );
+                documentStartPageNumber( nDoc ), documentEndPageNumber( nDoc ));
             pTargetView->GetWrtShell().EndAction();
             //then save it
             OUString sOutPath = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
@@ -801,12 +844,10 @@ IMPL_LINK_NOARG(SwMailMergeOutputPage, PrintHdl_Impl)
             nEnd = rConfigItem.GetMergedDocumentCount();
     }
     rConfigItem.SetPrintRange( (sal_uInt16)nBegin, (sal_uInt16)nEnd );
-    SwDocMergeInfo& rStartInfo = rConfigItem.GetDocumentMergeInfo(nBegin);
-    SwDocMergeInfo& rEndInfo = rConfigItem.GetDocumentMergeInfo(nEnd - 1);
 
-    OUString sPages(OUString::number( rStartInfo.nStartPageInTarget ));
+    OUString sPages(OUString::number( documentStartPageNumber( nBegin )));
     sPages += " - ";
-    sPages += OUString::number(  rEndInfo.nEndPageInTarget );
+    sPages += OUString::number( documentEndPageNumber( nEnd - 1 ));
 
     pTargetView->SetMailMergeConfigItem(&rConfigItem, 0, false);
     if(m_pTempPrinter)
@@ -1092,7 +1133,7 @@ IMPL_LINK(SwMailMergeOutputPage, SendDocumentsHdl_Impl, PushButton*, pButton)
         pTempView->GetDocShell()->GetDoc()->ReplaceDefaults( *pTargetView->GetDocShell()->GetDoc());
         pTempView->GetDocShell()->GetDoc()->ReplaceDocumentProperties( *pTargetView->GetDocShell()->GetDoc(), true );
         pTargetView->GetWrtShell().PastePages(pTempView->GetWrtShell(),
-                (sal_uInt16)rInfo.nStartPageInTarget, (sal_uInt16)rInfo.nEndPageInTarget );
+            documentStartPageNumber( nDoc ), documentEndPageNumber( nDoc ));
         pTargetView->GetWrtShell().EndAction();
 
         //then save it
diff --git a/sw/source/ui/dbui/mmoutputpage.hxx b/sw/source/ui/dbui/mmoutputpage.hxx
index 7355016..a31ddea 100644
--- a/sw/source/ui/dbui/mmoutputpage.hxx
+++ b/sw/source/ui/dbui/mmoutputpage.hxx
@@ -116,6 +116,10 @@ class SwMailMergeOutputPage : public svt::OWizardPage
     DECL_LINK(SendDocumentsHdl_Impl, PushButton*);
     DECL_LINK(DocumentSelectionHdl_Impl, RadioButton*);
     DECL_LINK(SaveCancelHdl_Impl, void *);
+
+    int documentStartPageNumber( int document ) const;
+    int documentEndPageNumber( int document ) const;
+
 protected:
         virtual bool    canAdvance() const SAL_OVERRIDE;
         virtual void    ActivatePage() SAL_OVERRIDE;
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6f17f51..c6f48fe 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1123,12 +1123,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             else
                                 pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
 
-                            sal_uInt16 nStartPage = pTargetShell->GetPageCnt();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
-                            pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
+                            SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
                                 nStartingPageNo, pTargetPageDesc, nDocNo == 1);
-
                             // #i72820# calculate layout to be able to find the correct page index
                             pTargetShell->CalcLayout();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
@@ -1136,9 +1134,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             if (bMergeShell)
                             {
                                 SwDocMergeInfo aMergeInfo;
-                                aMergeInfo.nStartPageInTarget = nStartPage;
-                                aMergeInfo.nEndPageInTarget =
-                                    nStartPage + pSourceShell->GetPageCnt() - 1;
+                                aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "MailMergeInternalStart" + OUString::number( nStartRow ),
+                                    IDocumentMarkAccess::UNO_BOOKMARK );
                                 aMergeInfo.nDBRow = nStartRow;
                                 rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
                             }
diff --git a/sw/source/uibase/inc/mmconfigitem.hxx b/sw/source/uibase/inc/mmconfigitem.hxx
index feeaed8..8117cfd 100644
--- a/sw/source/uibase/inc/mmconfigitem.hxx
+++ b/sw/source/uibase/inc/mmconfigitem.hxx
@@ -38,11 +38,11 @@ namespace com{namespace sun{namespace star{
 
 class SwMailMergeConfigItem_Impl;
 class SwView;
+namespace sw { namespace mark { class IMark; }}
 
 struct SwDocMergeInfo
 {
-    long    nStartPageInTarget;
-    long    nEndPageInTarget;
+    sw::mark::IMark* startPageInTarget;
     long    nDBRow;
 };
 


More information about the Libreoffice-commits mailing list