[Libreoffice-commits] core.git: Branch 'private/jmux/mm-cleanup' - 788 commits - accessibility/source android/Bootstrap animations/Library_animcore.mk animations/source avmedia/source basctl/inc basctl/source basebmp/CppunitTest_basebmp.mk basebmp/inc basebmp/Library_basebmp.mk basebmp/Makefile basebmp/Module_basebmp.mk basebmp/README basebmp/source basebmp/StaticLibrary_basebmp.mk basebmp/test basegfx/source basegfx/test basic/source bin/find-german-comments bin/gen-iwyu-dummy-lib bin/lo-all-static-libs bin/update_pch canvas/source chart2/inc chart2/source clew/Library_clew.mk comphelper/CppunitTest_comphelper_ifcontainer.mk comphelper/CppunitTest_comphelper_test.mk comphelper/Library_comphelper.mk comphelper/Module_comphelper.mk comphelper/qa comphelper/source compilerplugins/clang config_host/config_cups.h.in config_host.mk.in configure.ac connectivity/inc connectivity/Module_connectivity.mk connectivity/source cppcanvas/source cppu/qa cui/inc cui/source dbaccess/source desktop/CppunitTest_des ktop_lib.mk desktop/inc desktop/Library_sofficeapp.mk desktop/qa desktop/source desktop/unx dictionaries distro-configs/LibreOfficeAndroidAarch64.conf distro-configs/LibreOfficeAndroid.conf distro-configs/LibreOfficeAndroidX86.conf download.lst drawinglayer/source editeng/inc editeng/qa editeng/source embeddedobj/source embedserv/source extensions/source external/boost external/cairo external/clucene external/firebird external/libetonyek external/liblangtag external/libxml2 external/libxmlsec external/libxslt external/Module_external.mk external/vigra extras/source filter/Configuration_filter.mk filter/Library_gie.mk filter/source forms/source formula/source fpicker/source framework/inc framework/Library_fwe.mk framework/README framework/source .gitignore helpcompiler/inc helpcompiler/source helpcontent2 hwpfilter/source i18nlangtag/qa i18nlangtag/source i18npool/inc i18npool/Library_localedata_euro.mk i18npool/source icon-themes/breeze icon-themes/elementary icon-themes/galaxy icon -themes/sifr icon-themes/tango idlc/inc idlc/source idl/inc idl/source include/basebmp include/basegfx include/basic include/comphelper include/connectivity include/cppuhelper include/dbaccess include/drawinglayer include/editeng include/filter include/formula include/framework include/helpcompiler include/i18nlangtag include/LibreOfficeKit include/linguistic include/o3tl include/oox include/osl include/sal include/sax include/sfx2 include/sot include/store include/svl include/svtools include/svx include/toolkit include/tools include/unotools include/vcl include/xmloff l10ntools/inc l10ntools/source libreofficekit/Module_libreofficekit.mk libreofficekit/Package_selectionhandles.mk libreofficekit/qa libreofficekit/source lingucomponent/Library_hyphen.mk lingucomponent/Library_spell.mk lingucomponent/source linguistic/source linguistic/workben lotuswordpro/Library_lwpft.mk lotuswordpro/source lotuswordpro/util Makefile.fetch mysqlc/source nlpsolver/src odk/config offapi/com officecfg/ registry oox/inc oox/source package/inc package/source postprocess/CppunitTest_services.mk postprocess/packimages qadevOOo/runner qadevOOo/tests readlicense_oo/license README.md registry/source reportbuilder/java reportdesign/inc reportdesign/source RepositoryExternal.mk Repository.mk RepositoryModule_build.mk RepositoryModule_host.mk rsc/inc rsc/source salhelper/source sal/osl sal/qa sal/rtl sax/qa sax/source sc/inc sc/Library_sc.mk sc/Library_scui.mk scp2/InstallModule_ooo.mk scp2/source sc/qa scripting/Library_stringresource.mk scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sd/CppunitTest_sd_export_tests.mk sdext/source sd/inc sd/qa sd/source sd/uiconfig setup_native/scripts setup_native/source sfx2/inc sfx2/README sfx2/source shell/source slideshow/inc slideshow/opengl slideshow/Package_opengl.mk slideshow/source slideshow/test solenv/gbuild solenv/inc sot/source starmath/inc starmath/qa starmath/source store/source svgio/inc svgio/source svl/source svtools/i nc svtools/source svx/inc svx/Library_svx.mk svx/sdi svx/source svx/uiconfig sw/CppunitTest_sw_uiwriter.mk swext/mediawiki sw/inc sw/ooxmlexport_setup.mk sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_sglobal.mk sw/UIConfig_sweb.mk sw/UIConfig_swform.mk sw/UIConfig_swreport.mk sw/UIConfig_swriter.mk sw/UIConfig_swxform.mk sysui/desktop test/source toolkit/source tools/source translations ucbhelper/source ucb/Library_srtrs1.mk ucb/source UnoControls/inc unotools/source vbahelper/source vcl/android vcl/CppunitTest_vcl_bitmap_test.mk vcl/CppunitTest_vcl_fontmetric.mk vcl/CppunitTest_vcl_font.mk vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/Library_vclplug_gtk3.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/README vcl/source vcl/unx vcl/win vcl/workben wizards/com writerfilter/source writerperfect/CppunitTest_writerperfect_impress.mk writerperfect/source xmlhelp/source xmloff/inc xmloff/source xmloff/util xmlscript/source xmlsecurity/CppunitTest_xmlsecurity_signing. mk xmlsecurity/inc xmlsecurity/Library_xmlsecurity.mk xmlsecurity/Module_xmlsecurity.mk xmlsecurity/qa xmlsecurity/source

Jan-Marek Glogowski glogow at fbihome.de
Mon Jan 25 11:07:08 PST 2016


Rebased ref, commits from common ancestor:
commit fd01a68ba9eebe1ebc984d4b123c28b58e9e1ddb
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 25 19:36:26 2016 +0100

    MM: don't register files in recently used...
    
    ... in email and !bCreateSingleFile file mode. Also saves a bunch
    of instructions. For my simple document it was ~10% of the save
    time and 75% is the creation of the preview thumbnails...
    
    Change-Id: I14f7092007b1acfed6cbe0f2f4cd6eaecd32b514

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 781b53a..49d33bf 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -853,7 +853,11 @@ static bool lcl_SaveDoc(
         rWorkShell.ConvertFieldsToText();
 
     bool bAnyError = !xObjectShell->DoSaveAs(*pDstMed);
-    xObjectShell->DoSaveCompleted(pDstMed);
+
+    // Actually this should be a bool... so in case of email and individual
+    // files, where this is set, we skip the the recently used handling
+    if( !decodedURL )
+        xObjectShell->DoSaveCompleted( pDstMed );
     bAnyError = bAnyError || xObjectShell->GetError();
     if( bAnyError )
     {
commit e3ed69f86c945b01ba75f053a34a79d332fd1928
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 25 18:10:29 2016 +0100

    tdf#97318 MM: use working doc DB manager on save
    
    When saving the working document in !bCreateSingleFile mode, we
    have to restore the documents DB manager for two reasons:
    
    1. We otherwise would save the whole database content.
    2. We crash with embedded databases of the original DB manager.
    
    Change-Id: I9b209854703ec95c2c63c83019e857f2d26f753d

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 0fde862..781b53a 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1345,6 +1345,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         else
                         {
                             assert( bNeedsTempFiles );
+                            assert( pWorkShell->IsExpFieldsLocked() );
+
+                            // fields are locked, so it's fine to
+                            // restore the old / empty DB manager for save
+                            pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
+
                             // save merged document
                             OUString sFileURL;
                             if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
@@ -1353,6 +1359,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             {
                                 m_aMergeStatus = MergeStatus::ERROR;
                             }
+
+                            // back to the MM DB manager
+                            pWorkDoc->SetDBManager( this );
+
                             if( bMT_EMAIL && !IsMergeError() )
                             {
                                 {
commit 1f3d043c52dd63658a022b00ae99fff6e04272af
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 25 17:48:15 2016 +0100

    MM: correctly handle directory in dialog
    
    The directory selection dialog expects an URL. For convenience
    we present file URIs in the systems local file notation.
    
    So we need to convert the location notation to URI for the dialog.
    And since its a editable entry, append a directory delimiter to
    the value of the entry.
    
    Change-Id: Idff6f7d4b135eef087c61560b0603b9a6669dbf7

diff --git a/sw/source/ui/envelp/mailmrge.cxx b/sw/source/ui/envelp/mailmrge.cxx
index 107d8a7..34c7271 100644
--- a/sw/source/ui/envelp/mailmrge.cxx
+++ b/sw/source/ui/envelp/mailmrge.cxx
@@ -579,6 +579,7 @@ IMPL_LINK_NOARG_TYPED(SwMailMergeDlg, InsertPathHdl, Button*, void)
         SvtPathOptions aPathOpt;
         sPath = aPathOpt.GetWorkPath();
     }
+    sPath = INetURLObject::TryUrlFromSystemPathAsString( sPath, true );
 
     uno::Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
     uno::Reference < XFolderPicker2 > xFP = FolderPicker::create(xContext);
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index dc551c1..0fde862 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -2812,7 +2812,10 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
                     SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), *pWorkShell, aDescriptor );
                     aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
                     aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc();
-                    aMergeDesc.sPath = pImpl->pMergeDialog->GetPath(true);
+                    aMergeDesc.sPath = INetURLObject::TryUrlFromSystemPathAsString(
+                        pImpl->pMergeDialog->GetPath( true ) );
+                    if( !aMergeDesc.sPath.isEmpty() && !aMergeDesc.sPath.endsWith("/") )
+                        aMergeDesc.sPath += "/";
                     if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() )
                     {
                         aMergeDesc.sDBcolumn = pImpl->pMergeDialog->GetColumnName();
commit f1d001c9351b8d297ac06d09920ee4dab389bc75
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 22 21:25:11 2016 +0100

    tdf#96914 MM: don't round trip the source document
    
    To get a unmodified document, the mail merge via File -> Print
    used to write a document and reload it. This is not a problem with
    normal documents, but with embedded databases this results in a
    second database with the same name, which disposes the first
    registered database and the xResultSet from the mail merge dialog.
    
    As a workaround this just creates an internal copy, sets the
    correct database settings and resets the modified status.
    
    We still need a more general solution to handle documents with the
    same embedded DB name in a sane way, probably by making the embedded
    database a private object of the documents database manager.
    
    Change-Id: I20ddea30196d65cb89f69977867f012816ec6001

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 4f9eec3..b971a1c 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1623,7 +1623,7 @@ public:
     ::sw::UndoManager      & GetUndoManager();
     ::sw::UndoManager const& GetUndoManager() const;
 
-    SfxObjectShell* CreateCopy(bool bCallInitNew) const;
+    SfxObjectShell* CreateCopy(bool bCallInitNew, bool bEmpty) const;
     SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber,
                  bool bDeletePrevious = false, int physicalPageOffset = 0,
                  const sal_uLong nDocNo = 1);
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 4d7e04a..74908dd 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -867,7 +867,7 @@ void SwDoc::ReplaceCompatibilityOptions(const SwDoc& rSource)
     ((idx).GetNode().GetIndex() - GetNodes().GetEndOfExtras().GetIndex() - 1)
 #endif
 
-SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
+SfxObjectShell* SwDoc::CreateCopy( bool bCallInitNew, bool bEmpty ) const
 {
     SwDoc* pRet = new SwDoc;
 
@@ -890,14 +890,17 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
 
     pRet->ReplaceStyles(*this);
 
+    if( !bEmpty )
+    {
 #ifdef DBG_UTIL
-    SAL_INFO( "sw.createcopy", "CC-Nd-Src: " << CNTNT_DOC( this ) );
-    SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
+        SAL_INFO( "sw.createcopy", "CC-Nd-Src: " << CNTNT_DOC( this ) );
+        SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
 #endif
-    pRet->AppendDoc(*this, 0, bCallInitNew, 0, 0);
+        pRet->AppendDoc(*this, 0, bCallInitNew, 0, 0);
 #ifdef DBG_UTIL
-    SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
+        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( nullptr );
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 4365b98..dc551c1 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -41,7 +41,6 @@
 #include <com/sun/star/ui/dialogs/XFilePicker2.hpp>
 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
 #include <com/sun/star/uno/XNamingService.hpp>
-#include <com/sun/star/util/XCloseable.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <sfx2/fcontnr.hxx>
 #include <sfx2/filedlghelper.hxx>
@@ -136,6 +135,7 @@
 #include <calc.hxx>
 #include <dbfld.hxx>
 #include <DocumentFieldsManager.hxx>
+#include <IDocumentState.hxx>
 
 #include <memory>
 #include <comphelper/propertysequence.hxx>
@@ -897,6 +897,64 @@ static void lcl_PreparePrinterOptions(
     }
 }
 
+enum class WorkingDocType { SOURCE, TARGET, COPY };
+
+static SfxObjectShell* lcl_CreateWorkingDocument(
+    // input
+    const WorkingDocType aType, const SwDoc* pSourceDoc,
+    // optional input
+    const vcl::Window *pSourceWindow,
+    // optional in and output to swap the DB manager
+    SwDBManager** const pDBManager,
+    // optional output
+    SwView** const pView, SwWrtShell** const pWrtShell, SwDoc** const pDoc )
+{
+    SfxObjectShellRef xWorkObjectShell = pSourceDoc->CreateCopy( true, (aType == WorkingDocType::TARGET) );
+    SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkObjectShell, 0 );
+
+    if( pSourceWindow )
+    {
+        // the created window has to be located at the same position as the source window
+        vcl::Window& rTargetWindow = pWorkFrame->GetFrame().GetWindow();
+        rTargetWindow.SetPosPixel( pSourceWindow->GetPosPixel() );
+    }
+
+    SwView* pWorkView = static_cast< SwView* >( pWorkFrame->GetViewShell() );
+    SwWrtShell* pWorkWrtShell = pWorkView->GetWrtShellPtr();
+    pWorkView->AttrChangedNotify( pWorkWrtShell );// in order for SelectShell to be called
+    SwDoc* pWorkDoc = pWorkWrtShell->GetDoc();
+    pWorkDoc->ReplaceDocumentProperties( *pSourceDoc );
+
+    if( aType == WorkingDocType::TARGET )
+    {
+        assert( !pDBManager );
+        pWorkDoc->SetInMailMerge( true );
+    }
+    else
+    {
+        // We have to swap the DBmanager of the new doc, so we also need input
+        assert( pDBManager && *pDBManager );
+        SwDBManager *pWorkDBManager = pWorkDoc->GetDBManager();
+        pWorkDoc->SetDBManager( *pDBManager );
+        *pDBManager = pWorkDBManager;
+
+        if( aType == WorkingDocType::SOURCE )
+        {
+            // the GetDBData call constructs the data, if it's missing - kind of const...
+            pWorkWrtShell->ChgDBData( const_cast<SwDoc*>(pSourceDoc)->GetDBData() );
+            pWorkDoc->getIDocumentState().ResetModified();
+        }
+        else
+            pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
+    }
+
+    if( pView )     *pView     = pWorkView;
+    if( pWrtShell ) *pWrtShell = pWorkWrtShell;
+    if( pDoc )      *pDoc      = pWorkDoc;
+
+    return xWorkObjectShell;
+}
+
 /**
  * Please have a look at the README in the same directory, before you make
  * larger changes in this function!
@@ -983,8 +1041,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             }
         }
 
-        // Try saving the source document
-        SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher();
         SwDocShell* pSourceDocSh = pSourceShell->GetView().GetDocShell();
 
         uno::Reference<document::XDocumentProperties> xSourceDocProps;
@@ -995,6 +1051,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             assert( xSourceDocProps.is() && "DocumentProperties is null" );
         }
 
+        // Try saving the source document
+        SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher();
         if( !bMT_SHELL && pSourceDocSh->IsModified() )
             pSfxDispatcher->Execute( pSourceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SfxCallMode::SYNCHRON|SfxCallMode::RECORD);
         if( bMT_SHELL || !pSourceDocSh->IsModified() )
@@ -1064,37 +1122,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             if( bCreateSingleFile )
             {
                 // create a target docshell to put the merged document into
-                xTargetDocShell = new SwDocShell( SfxObjectCreateMode::STANDARD );
-                xTargetDocShell->DoInitNew();
+                xTargetDocShell = lcl_CreateWorkingDocument( WorkingDocType::TARGET,
+                    pSourceDocSh->GetDoc(), bMT_SHELL ? pSourceWindow : nullptr,
+                    nullptr, &pTargetView, &pTargetShell, &pTargetDoc );
                 if (nMaxDumpDocs)
                     lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
-                SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
-                if (bMT_SHELL && pSourceWindow) {
-                    //the created window has to be located at the same position as the source window
-                    vcl::Window& rTargetWindow = pTargetFrame->GetFrame().GetWindow();
-                    rTargetWindow.SetPosPixel(pSourceWindow->GetPosPixel());
-                }
-
-                pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
-
-                //initiate SelectShell() to create sub shells
-                pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
-                pTargetShell = pTargetView->GetWrtShellPtr();
-                pTargetDoc = pTargetShell->GetDoc();
-                pTargetDoc->SetInMailMerge(true);
 
-                //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
+                // determine the page style and number used at the start of the source document
                 pSourceShell->SttEndDoc(true);
                 nStartingPageNo = pSourceShell->GetVirtPageNum();
-
-                // copy compatibility options
-                pTargetDoc->ReplaceCompatibilityOptions( *pSourceShell->GetDoc() );
-                // #72821# copy dynamic defaults
-                pTargetDoc->ReplaceDefaults( *pSourceShell->GetDoc() );
-                pTargetDoc->ReplaceDocumentProperties( *pSourceShell->GetDoc() );
             }
 
             // Progress, to prohibit KeyInputs
@@ -1131,6 +1167,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             SwView*            pWorkView             = nullptr;
             SwDoc*             pWorkDoc              = nullptr;
             SwDBManager*       pWorkDocOrigDBManager = nullptr;
+            SwWrtShell*        pWorkShell            = nullptr;
             bool               bWorkDocInitialized   = false;
 
             do
@@ -1211,41 +1248,29 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFeport )
                         {
                             assert( !xWorkDocSh.Is());
-                            // copy the source document
-                            xWorkDocSh = pSourceDocSh->GetDoc()->CreateCopy( true );
-
-                            //create a view frame for the document
-                            pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() );
-                            //request the layout calculation
-                            SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
-                            pWorkView->AttrChangedNotify( &rWorkShell );// in order for SelectShell to be called
-
-                            pWorkDoc = rWorkShell.GetDoc();
-                            pWorkDoc->ReplaceDocumentProperties( *pSourceDocSh->GetDoc());
+                            pWorkDocOrigDBManager = this;
+                            xWorkDocSh = lcl_CreateWorkingDocument( WorkingDocType::COPY,
+                                pSourceDocSh->GetDoc(), nullptr, &pWorkDocOrigDBManager,
+                                &pWorkView, &pWorkShell, &pWorkDoc );
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
-                            pWorkDocOrigDBManager = pWorkDoc->GetDBManager();
-                            pWorkDoc->SetDBManager( this );
-                            pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
 
                             // #i69458# lock fields to prevent access to the result set while calculating layout
                             // tdf#92324: and do not unlock: keep document locked during printing to avoid
                             // ExpFields update during printing, generation of preview, etc.
-                            rWorkShell.LockExpFields();
-                            rWorkShell.CalcLayout();
+                            pWorkShell->LockExpFields();
+                            pWorkShell->CalcLayout();
                         }
 
-                        SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
-
                         EMIT_SW_EVENT(FIELD_MERGE, xWorkDocSh);
 
                         // tdf#92324: Allow ExpFields update only by explicit instruction to avoid
                         // database cursor movement on any other fields update, for example during
                         // print preview and other operations
-                        if ( rWorkShell.IsExpFieldsLocked() )
-                            rWorkShell.UnlockExpFields();
-                        rWorkShell.SwViewShell::UpdateFields();
-                        rWorkShell.LockExpFields();
+                        if ( pWorkShell->IsExpFieldsLocked() )
+                            pWorkShell->UnlockExpFields();
+                        pWorkShell->SwViewShell::UpdateFields();
+                        pWorkShell->LockExpFields();
 
                         EMIT_SW_EVENT(FIELD_MERGE_FINISHED, xWorkDocSh);
 
@@ -1268,11 +1293,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             // prepare working copy and target to append
 
                             pWorkDoc->RemoveInvisibleContent();
-                            rWorkShell.ConvertFieldsToText();
-                            rWorkShell.SetNumberingRestart();
+                            pWorkShell->ConvertFieldsToText();
+                            pWorkShell->SetNumberingRestart();
                             if( bSynchronizedDoc )
                             {
-                                lcl_RemoveSectionLinks( rWorkShell );
+                                lcl_RemoveSectionLinks( *pWorkShell );
                             }
 
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
@@ -1281,9 +1306,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             // append the working document to the target document
                             if( targetDocPageCount % 2 == 1 )
                                 ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
-                            SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
+                            SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc( *pWorkDoc,
                                 nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo);
-                            targetDocPageCount += rWorkShell.GetPageCnt();
+                            targetDocPageCount += pWorkShell->GetPageCnt();
 
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
@@ -1324,7 +1349,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             OUString sFileURL;
                             if( !lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
                                               &rMergeDescriptor.aSaveToFilterData, bIsPDFeport,
-                                              xWorkDocSh, rWorkShell, &sFileURL ) )
+                                              xWorkDocSh, *pWorkShell, &sFileURL ) )
                             {
                                 m_aMergeStatus = MergeStatus::ERROR;
                             }
@@ -2703,7 +2728,7 @@ void SwDBManager::LoadAndRegisterEmbeddedDataSource(const SwDBData& rData, const
     if (sDataSource.isEmpty())
         sDataSource = "EmbeddedDatabase";
 
-    SwDBManager::RevokeDataSource(rData.sDataSource);
+    SwDBManager::RevokeDataSource( sDataSource );
 
     // Encode the stream name and the real path into a single URL.
     const INetURLObject& rURLObject = rDocShell.GetMedium()->GetURLObject();
@@ -2712,7 +2737,7 @@ void SwDBManager::LoadAndRegisterEmbeddedDataSource(const SwDBData& rData, const
     aURL += "/" + INetURLObject::encode(m_sEmbeddedName, INetURLObject::PART_FPATH, INetURLObject::ENCODE_ALL);
 
     uno::Reference<uno::XInterface> xDataSource(xDatabaseContext->getByName(aURL), uno::UNO_QUERY);
-    xDatabaseContext->registerObject(rData.sDataSource, xDataSource);
+    xDatabaseContext->registerObject( sDataSource, xDataSource );
 }
 
 void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
@@ -2774,47 +2799,17 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
 
         EMIT_SW_EVENT(MAIL_MERGE, xDocShell);
         {
-            //copy rSh to aTempFile
-            OUString sTempURL;
-            const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
-                        FILTER_XML,
-                        SwDocShell::Factory().GetFilterContainer() );
-            try
-            {
-                uno::Sequence< beans::PropertyValue > aValues(1);
-                beans::PropertyValue* pValues = aValues.getArray();
-                pValues[0].Name = "FilterName";
-                pValues[0].Value <<= OUString(pSfxFlt->GetFilterName());
-                uno::Reference< frame::XStorable > xStore( xDocShell->GetModel(), uno::UNO_QUERY);
-                sTempURL = URIHelper::SmartRel2Abs( INetURLObject(), utl::TempFile::CreateTempName() );
-                xStore->storeToURL( sTempURL, aValues );
-            }
-            catch(const uno::Exception&)
             {
-            }
-            if( xDocShell->GetError() )
-            {
-                // error message ??
-                ErrorHandler::HandleError( xDocShell->GetError() );
-            }
-            else
-            {
-                // the shell will be explicitly closed, but it is more safe to use SfxObjectShellLock here
-                // especially for the case that the loading has failed
-                SfxObjectShellLock xWorkDocSh( new SwDocShell( SfxObjectCreateMode::INTERNAL ));
-                SfxMedium* pWorkMed = new SfxMedium( sTempURL, STREAM_STD_READ );
-                pWorkMed->SetFilter( pSfxFlt );
-                if( xWorkDocSh->DoLoad(pWorkMed) )
                 {
-                    SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
-                    SwView *pView = static_cast<SwView*>( pFrame->GetViewShell() );
-                    pView->AttrChangedNotify( &pView->GetWrtShell() );// in order for SelectShell to be called
-                    //set the current DBManager
-                    SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc();
-                    SwDBManager* pWorkDocOrigDBManager = pWorkDoc->GetDBManager();
-                    pWorkDoc->SetDBManager( this );
-
-                    SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
+                    SwWrtShell  *pWorkShell;
+                    SwDoc       *pWorkDoc;
+                    SwDBManager *pWorkDocOrigDBManager = this;
+                    SfxObjectShellLock xWorkDocSh = lcl_CreateWorkingDocument(
+                        WorkingDocType::SOURCE, rSh.GetDoc(), nullptr,
+                        &pWorkDocOrigDBManager, nullptr, &pWorkShell, &pWorkDoc );
+
+                    // prepare mail merge descriptor
+                    SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), *pWorkShell, aDescriptor );
                     aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
                     aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc();
                     aMergeDesc.sPath = pImpl->pMergeDialog->GetPath(true);
@@ -2823,27 +2818,12 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
                         aMergeDesc.sDBcolumn = pImpl->pMergeDialog->GetColumnName();
                     }
 
-                    MergeNew(aMergeDesc);
+                    MergeNew( aMergeDesc );
 
                     pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
-                    //close the temporary file
-                    uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY );
-                    if (xClose.is())
-                    {
-                        try
-                        {
-                            //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
-                            //! I.e. now that object is responsible for closing the model and doc shell.
-                            xClose->close( sal_True );
-                        }
-                        catch (const uno::Exception&)
-                        {
-                        }
-                    }
+                    xWorkDocSh->DoClose();
                 }
             }
-            //remove the temporary file
-            SWUnoHelper::UCB_DeleteFile( sTempURL );
         }
         EMIT_SW_EVENT(MAIL_MERGE_END, xDocShell);
 
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 2ebaf0e..085fa6a 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3090,7 +3090,7 @@ uno::Reference< util::XCloneable > SwXTextDocument::createClone(  ) throw (uno::
     // SfxObjectShellRef is used here, since the model should control object lifetime after creation
     // and thus SfxObjectShellLock is not allowed here
     // the model holds reference to the shell, so the shell will not destructed at the end of method
-    SfxObjectShellRef pShell = pDocShell->GetDoc()->CreateCopy(false);
+    SfxObjectShellRef pShell = pDocShell->GetDoc()->CreateCopy(false, false);
     uno::Reference< frame::XModel > xNewModel = pShell->GetModel();
     uno::Reference< embed::XStorage > xNewStorage = ::comphelper::OStorageHelper::GetTemporaryStorage( );
     uno::Sequence< beans::PropertyValue > aTempMediaDescriptor;
commit 5ca0adc7c08bbae67ffb82ba3072cc4ce8fa7307
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Wed Jan 20 10:48:37 2016 +0100

    tdf#95292 MM: cleanup bEndOfDB handling
    
    bEndOfDB was handled inconsistently in ToNextRecord for record
    selections and normal record iteration. The new unified semantics
    are defined to set bEndOfDB for the first failing record fetch.
    
    This includes a rename of the function ExistsNextRecord, which
    did never check for a next record, but just verified the current
    record set to be valid.
    
    This way we can also drop the bAfterSelection selection, which
    was just needed for the inconsistent bEndOfDB handling.
    
    Change-Id: Ibbd7ae95e5969b51e32f44b442e5dc778655e8a9

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 6dea6d6..36f12b3 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -109,14 +109,12 @@ struct SwDSParam : public SwDBData
     css::uno::Sequence<  css::uno::Any >               aSelection;
     bool bScrollable;
     bool bEndOfDB;
-    bool bAfterSelection;
     long nSelectionIndex;
 
     SwDSParam(const SwDBData& rData) :
         SwDBData(rData),
         bScrollable(false),
         bEndOfDB(false),
-        bAfterSelection(false),
         nSelectionIndex(0)
         {}
 
@@ -128,16 +126,13 @@ struct SwDSParam : public SwDBData
         aSelection(rSelection),
         bScrollable(true),
         bEndOfDB(false),
-        bAfterSelection(false),
         nSelectionIndex(0)
         {}
 
-        void CheckEndOfDB()
-        {
-            if(bEndOfDB)
-                bAfterSelection = true;
-        }
+    inline bool HasValidRecord() const
+        { return( !bEndOfDB && xResultSet.is() ); }
 };
+
 typedef std::vector<std::unique_ptr<SwDSParam>> SwDSParams_t;
 
 struct SwMergeDescriptor
@@ -266,6 +261,9 @@ friend class SwConnectionDisposedListener_Impl;
                                         const SwMergeDescriptor& rMergeDescriptor,
                                         vcl::Window* pParent );
 
+    SAL_DLLPRIVATE bool ToNextMergeRecord( const sal_uInt16 nSkip = 0 );
+    SAL_DLLPRIVATE bool IsValidMergeRecord() const;
+
     SwDBManager(SwDBManager const&) = delete;
     SwDBManager& operator=(SwDBManager const&) = delete;
 
@@ -363,10 +361,8 @@ public:
                                       OUString &rResult, double *pNumber);
     bool            FillCalcWithMergeData(SvNumberFormatter *pDocFormatter,
                                           sal_uInt16 nLanguage, bool asString, SwCalc &aCalc);
-    bool            ToNextMergeRecord(const sal_uInt16 nSkip = 0);
     bool            ToNextRecord(const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType = -1);
 
-    bool            ExistsNextRecord()const;
     sal_uInt32      GetSelectedRecordId();
     bool            ToRecordId(sal_Int32 nSet);
 
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index c508908..4365b98 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -355,7 +355,6 @@ static bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos)
                 sal_Int32 nPos = 0;
                 pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
                 pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
-                pParam->CheckEndOfDB();
                 bRet = !pParam->bEndOfDB;
             }
         }
@@ -1419,7 +1418,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     bFreezedLayouts = true;
                 }
             } while( IsMergeOk() &&
-                (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
+                ((bSynchronizedDoc && (nStartRow != nEndRow)) ? IsValidMergeRecord() : ToNextMergeRecord()));
 
             if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
             {
@@ -1941,7 +1940,7 @@ bool SwDBManager::GetColumnCnt(const OUString& rSourceName, const OUString& rTab
         if(!bFound)
             return false;
     }
-    if(pFound->xResultSet.is() && !pFound->bAfterSelection)
+    if( pFound->HasValidRecord() )
     {
         sal_Int32 nOldRow = 0;
         try
@@ -1968,7 +1967,7 @@ bool SwDBManager::GetColumnCnt(const OUString& rSourceName, const OUString& rTab
 bool    SwDBManager::GetMergeColumnCnt(const OUString& rColumnName, sal_uInt16 nLanguage,
                                    OUString &rResult, double *pNumber)
 {
-    if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is() || pImpl->pMergeData->bAfterSelection )
+    if( !IsValidMergeRecord() )
     {
         rResult.clear();
         return false;
@@ -1987,30 +1986,21 @@ bool SwDBManager::ToNextMergeRecord( const sal_uInt16 nSkip )
 bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter,
                                          sal_uInt16 nLanguage, bool asString, SwCalc &rCalc )
 {
-    if (!(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is()))
+    if( !IsValidMergeRecord() )
         return false;
 
     uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
-    if(xColsSupp.is())
+    if( !xColsSupp.is() )
+        return false;
+
     {
         uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
         const uno::Sequence<OUString> aColNames = xCols->getElementNames();
         const OUString* pColNames = aColNames.getConstArray();
         OUString aString;
 
-        const bool bExistsNextRecord = ExistsNextRecord();
-
         for( int nCol = 0; nCol < aColNames.getLength(); nCol++ )
         {
-            const OUString &rColName = pColNames[nCol];
-
-            // empty variables, if no more records;
-            if( !bExistsNextRecord )
-            {
-                rCalc.VarChange( rColName, 0 );
-                continue;
-            }
-
             // get the column type
             sal_Int32 nColumnType = sdbc::DataType::SQLNULL;
             uno::Any aCol = xCols->getByName( pColNames[nCol] );
@@ -2050,9 +2040,9 @@ bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter,
                 rCalc.VarChange( pColNames[nCol], aValue );
             }
         }
-        return bExistsNextRecord;
     }
-    return false;
+
+    return true;
 }
 
 bool SwDBManager::ToNextRecord(
@@ -2080,35 +2070,33 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip, const S
 {
     bool bRet = true;
 
-    assert( action == SwDBNextRecord::NEXT || action == SwDBNextRecord::FIRST );
+    assert( SwDBNextRecord::NEXT == action ||
+         (SwDBNextRecord::FIRST == action && pParam) );
+    if( nullptr == pParam )
+        return false;
 
     if( action == SwDBNextRecord::FIRST )
     {
         pParam->nSelectionIndex = 0;
-        pParam->bEndOfDB        =
-        pParam->bAfterSelection = false;
+        pParam->bEndOfDB        = false;
     }
 
-    if( !pParam || !pParam->xResultSet.is() || pParam->bEndOfDB ||
-            (pParam->aSelection.getLength() &&
-             pParam->aSelection.getLength() <= pParam->nSelectionIndex) )
-    {
-        if( pParam )
-            pParam->CheckEndOfDB();
+    if( !pParam->HasValidRecord() )
         return false;
-    }
+
     try
     {
         if( pParam->aSelection.getLength() )
         {
-            sal_Int32 nPos = 0;
-            pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
-            pParam->nSelectionIndex += 1 + nSkip;
-            pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
-            pParam->CheckEndOfDB();
-            bRet = !pParam->bEndOfDB;
             if( pParam->nSelectionIndex >= pParam->aSelection.getLength() )
                 pParam->bEndOfDB = true;
+            else
+            {
+                sal_Int32 nPos = 0;
+                pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
+                pParam->nSelectionIndex += 1 + nSkip;
+                pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
+            }
         }
         else if( action == SwDBNextRecord::FIRST )
         {
@@ -2116,8 +2104,6 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip, const S
                 pParam->bEndOfDB = !pParam->xResultSet->first();
             else
                 pParam->bEndOfDB = !pParam->xResultSet->absolute( nSkip );
-            pParam->CheckEndOfDB();
-            bRet = !pParam->bEndOfDB;
         }
         else
         {
@@ -2131,15 +2117,15 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip, const S
                 // next returned true but it didn't move
                 pParam->bEndOfDB = true;
             }
-            pParam->CheckEndOfDB();
-            bRet = !pParam->bEndOfDB;
             pParam->nSelectionIndex += 1 + nSkip;
         }
+
+        bRet = !pParam->bEndOfDB;
     }
     catch( const uno::Exception &e )
     {
         pParam->bEndOfDB = true;
-        pParam->CheckEndOfDB();
+        bRet = false;
         // we allow merging with empty databases, so don't warn on init
         SAL_WARN_IF(action == SwDBNextRecord::NEXT,
                     "sw.mailmerge", "exception in ToNextRecord(): " << e.Message);
@@ -2150,9 +2136,9 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip, const S
 // synchronized labels contain a next record field at their end
 // to assure that the next page can be created in mail merge
 // the cursor position must be validated
-bool SwDBManager::ExistsNextRecord() const
+bool SwDBManager::IsValidMergeRecord() const
 {
-    return pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB;
+    return( pImpl->pMergeData && pImpl->pMergeData->HasValidRecord() );
 }
 
 sal_uInt32  SwDBManager::GetSelectedRecordId()
@@ -2185,7 +2171,6 @@ bool SwDBManager::ToRecordId(sal_Int32 nSet)
     {
         bRet = lcl_MoveAbsolute(pImpl->pMergeData, nAbsPos);
         pImpl->pMergeData->bEndOfDB = !bRet;
-        pImpl->pMergeData->CheckEndOfDB();
     }
     return bRet;
 }
@@ -2237,8 +2222,6 @@ bool SwDBManager::OpenDataSource(const OUString& rDataSource, const OUString& rT
 
             //after executeQuery the cursor must be positioned
             pFound->bEndOfDB = !pFound->xResultSet->next();
-            pFound->bAfterSelection = false;
-            pFound->CheckEndOfDB();
             ++pFound->nSelectionIndex;
         }
         catch (const uno::Exception&)
@@ -2321,7 +2304,6 @@ void    SwDBManager::CloseAll(bool bIncludingMerge)
         if(bIncludingMerge || pParam.get() != pImpl->pMergeData)
         {
             pParam->nSelectionIndex = 0;
-            pParam->bAfterSelection = false;
             pParam->bEndOfDB = false;
             try
             {
commit 4a8ef3728e1bf1bf3f3ad8f05f004016d91b1e24
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 18 16:48:54 2016 +0100

    MM: move SwPageDesc handling into SwDoc::AppendDoc
    
    If you append a doc, you want to handle styles correctly. So it's
    actually the correct way to handle the styles in AppendDoc.
    
    The nDocNo is used instead of a boolean to speed up finding better
    unique names in the mail merge case.
    
    Change-Id: I4b16e89588164b9e0763759c7d719dfc204b63a1

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index d6c5c08..4f9eec3 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1625,7 +1625,8 @@ public:
 
     SfxObjectShell* CreateCopy(bool bCallInitNew) const;
     SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber,
-                 SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false, int physicalPageOffset = 0 );
+                 bool bDeletePrevious = false, int physicalPageOffset = 0,
+                 const sal_uLong nDocNo = 1);
 
     /**
      * 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 9f44b12..4d7e04a 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -109,6 +109,7 @@
 #include <fldbas.hxx>
 #include <wrtsh.hxx>
 #include <unocrsr.hxx>
+#include <fmthdft.hxx>
 
 #include <cmdid.h>
 
@@ -893,7 +894,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
     SAL_INFO( "sw.createcopy", "CC-Nd-Src: " << CNTNT_DOC( this ) );
     SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
 #endif
-    pRet->AppendDoc(*this, 0, nullptr, bCallInitNew);
+    pRet->AppendDoc(*this, 0, bCallInitNew, 0, 0);
 #ifdef DBG_UTIL
     SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
 #endif
@@ -906,9 +907,45 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
     return pRetShell;
 }
 
+// save bulk letters as single documents
+static OUString lcl_FindUniqueName(SwWrtShell* pTargetShell, const OUString& rStartingPageDesc, sal_uLong nDocNo )
+{
+    do
+    {
+        OUString sTest = rStartingPageDesc;
+        sTest += OUString::number( nDocNo );
+        if( !pTargetShell->FindPageDescByName( sTest ) )
+            return sTest;
+        ++nDocNo;
+    }
+    while( true );
+}
+
+static void lcl_CopyFollowPageDesc(
+                            SwWrtShell& rTargetShell,
+                            const SwPageDesc& rSourcePageDesc,
+                            const SwPageDesc& rTargetPageDesc,
+                            const sal_uLong nDocNo )
+{
+    //now copy the follow page desc, too
+    const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow();
+    OUString sFollowPageDesc = pFollowPageDesc->GetName();
+    if( sFollowPageDesc != rSourcePageDesc.GetName() )
+    {
+        SwDoc* pTargetDoc = rTargetShell.GetDoc();
+        OUString sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo );
+        SwPageDesc* pTargetFollowPageDesc = pTargetDoc->MakePageDesc(sNewFollowPageDesc);
+
+        pTargetDoc->CopyPageDesc(*pFollowPageDesc, *pTargetFollowPageDesc, false);
+        SwPageDesc aDesc(rTargetPageDesc);
+        aDesc.SetFollow(pTargetFollowPageDesc);
+        pTargetDoc->ChgPageDesc(rTargetPageDesc.GetName(), aDesc);
+    }
+}
+
 // 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, int pageOffset)
+                             bool const bDeletePrevious, int pageOffset, const sal_uLong nDocNo)
 {
     // GetEndOfExtras + 1 = StartOfContent == no content node!
     // this ensures, that we have at least two nodes in the SwPaM.
@@ -950,12 +987,43 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu
 #endif
 
     SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell();
+    SwPageDesc* pTargetPageDesc = nullptr;
+
     if ( pTargetShell ) {
 #ifdef DBG_UTIL
         SAL_INFO( "sw.docappend", "Has target write shell" );
 #endif
         pTargetShell->StartAllAction();
 
+        if( nDocNo > 0 )
+        {
+            // #i72517# put the styles to the target document
+            // if the source uses headers or footers the target document
+            // needs inidividual page styles
+            const SwWrtShell *pSourceShell = rSource.GetDocShell()->GetWrtShell();
+            const SwPageDesc *pSourcePageDesc = &pSourceShell->GetPageDesc(
+                                                    pSourceShell->GetCurPageDesc());
+            const OUString sStartingPageDesc = pSourcePageDesc->GetName();
+            const SwFrameFormat& rMaster = pSourcePageDesc->GetMaster();
+            const bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
+                                                     rMaster.GetFooter().IsActive();
+            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 );
+                pTargetPageDesc = this->MakePageDesc( sNewPageDescName );
+                if( pTargetPageDesc )
+                {
+                    this->CopyPageDesc( *pSourcePageDesc, *pTargetPageDesc, false );
+                    lcl_CopyFollowPageDesc( *pTargetShell, *pSourcePageDesc, *pTargetPageDesc, nDocNo );
+                }
+            }
+            else
+                pTargetPageDesc = pTargetShell->FindPageDescByName( sStartingPageDesc );
+        }
+
         // Otherwise we have to handle SwPlaceholderNodes as first node
         if ( pTargetPageDesc ) {
             OUString name = pTargetPageDesc->GetName();
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index e8a6d10..c508908 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -784,41 +784,6 @@ SwDBManager::~SwDBManager()
     }
 }
 
-// save bulk letters as single documents
-static OUString lcl_FindUniqueName(SwWrtShell* pTargetShell, const OUString& rStartingPageDesc, sal_uLong nDocNo )
-{
-    do
-    {
-        OUString sTest = rStartingPageDesc;
-        sTest += OUString::number( nDocNo );
-        if( !pTargetShell->FindPageDescByName( sTest ) )
-            return sTest;
-        ++nDocNo;
-    }while(true);
-}
-
-static void lcl_CopyFollowPageDesc(
-                            SwWrtShell& rTargetShell,
-                            const SwPageDesc& rSourcePageDesc,
-                            const SwPageDesc& rTargetPageDesc,
-                            const sal_uLong nDocNo )
-{
-    //now copy the follow page desc, too
-    const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow();
-    OUString sFollowPageDesc = pFollowPageDesc->GetName();
-    if( sFollowPageDesc != rSourcePageDesc.GetName() )
-    {
-        SwDoc* pTargetDoc = rTargetShell.GetDoc();
-        OUString sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo );
-        SwPageDesc* pTargetFollowPageDesc = pTargetDoc->MakePageDesc(sNewFollowPageDesc);
-
-        pTargetDoc->CopyPageDesc(*pFollowPageDesc, *pTargetFollowPageDesc, false);
-        SwPageDesc aDesc(rTargetPageDesc);
-        aDesc.SetFollow(pTargetFollowPageDesc);
-        pTargetDoc->ChgPageDesc(rTargetPageDesc.GetName(), aDesc);
-    }
-}
-
 static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
 {
     //reset all links of the sections of synchronized labels
@@ -1070,10 +1035,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             SfxObjectShellRef xTargetDocShell;
 
             std::unique_ptr< utl::TempFile > aTempFile;
-            OUString sModifiedStartingPageDesc;
-            OUString sStartingPageDesc;
             sal_uInt16 nStartingPageNo = 0;
-            bool bPageStylesWithHeaderFooter = false;
 
             vcl::Window *pSourceWindow = nullptr;
             VclPtr<CancelableDialog> pProgressDlg;
@@ -1128,14 +1090,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 //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();
-
-                // #i72517#
-                const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
-                const SwFrameFormat& rMaster = pSourcePageDesc->GetMaster();
-                bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
-                                                rMaster.GetFooter().IsActive();
 
                 // copy compatibility options
                 pTargetDoc->ReplaceCompatibilityOptions( *pSourceShell->GetDoc() );
@@ -1322,29 +1276,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 lcl_RemoveSectionLinks( rWorkShell );
                             }
 
-                            // #i72517# put the styles to the target document
-                            // if the source uses headers or footers each working document
-                            // needs inidividual page styles
-                            SwPageDesc* pTargetPageDesc = nullptr;
-                            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 );
-                                pTargetPageDesc = pTargetDoc->MakePageDesc( sNewPageDescName );
-                                const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
-
-                                if(pWorkPageDesc && pTargetPageDesc)
-                                {
-                                    pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, false );
-                                    sModifiedStartingPageDesc = sNewPageDescName;
-                                    lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
-                                }
-                            }
-                            else
-                                pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
-
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
 
@@ -1352,7 +1283,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             if( targetDocPageCount % 2 == 1 )
                                 ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
                             SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
-                                nStartingPageNo, pTargetPageDesc, !bWorkDocInitialized, targetDocPageCount);
+                                nStartingPageNo, !bWorkDocInitialized, targetDocPageCount, nDocNo);
                             targetDocPageCount += rWorkShell.GetPageCnt();
 
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
commit 0c57e290086381b5efd8d60509ed396f7591971c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 18 15:04:12 2016 +0100

    MM: merge cancel and error variable
    
    An error always includes the "cancel", while a cancel doesn't have
    to be an error. So merge handling by using an enum.
    
    Change-Id: I154dccbd3063d7ce37ee3cb90b4f193cb1edd466

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 8ad8ed9..6dea6d6 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -230,14 +230,12 @@ class SW_DLLPUBLIC SwDBManager
 {
 friend class SwConnectionDisposedListener_Impl;
 
-    /** Mail merge cancel indicator
+    enum class MergeStatus
+    {
+        OK = 0, CANCEL, ERROR
+    };
 
-       TODO: convert m_bCancel to a three state escalating enum
-       run, cancel, error. Not sure if this helps readability /
-       further code cleanup, but it would be easier to follow the
-       seamantics and we could get rid of bNoError in MergeMailFiles
-     */
-    bool            m_bCancel;
+    MergeStatus     m_aMergeStatus;     ///< current / last merge status
     bool            bInitDBFields : 1;
     bool            bInMerge    : 1;    ///< merge process active
     bool            bMergeSilent : 1;   ///< suppress display of dialogs/boxes (used when called over API)
@@ -296,6 +294,10 @@ public:
     bool            MergeNew( const SwMergeDescriptor& rMergeDesc, vcl::Window* pParent = nullptr );
     void            MergeCancel();
 
+    inline bool     IsMergeOk()     { return MergeStatus::OK     == m_aMergeStatus; };
+    inline bool     IsMergeCancel() { return MergeStatus::CANCEL <= m_aMergeStatus; };
+    inline bool     IsMergeError()  { return MergeStatus::ERROR  <= m_aMergeStatus; };
+
     /// Initialize data fields that lack name of database.
     inline bool     IsInitDBFields() const  { return bInitDBFields; }
     inline void     SetInitDBFields(bool b) { bInitDBFields = b;    }
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 08716c2..e8a6d10 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -753,7 +753,7 @@ void SwDBManager::GetColumnNames(ListBox* pListBox,
 }
 
 SwDBManager::SwDBManager(SwDoc* pDoc)
-    : m_bCancel(false)
+    : m_aMergeStatus( MergeStatus::OK )
     , bInitDBFields(false)
     , bInMerge(false)
     , bMergeSilent(false)
@@ -981,10 +981,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     OUString                            sMailBodyMimeType;
     rtl_TextEncoding                    sMailEncoding = ::osl_getThreadTextEncoding();
 
-    // bNoError should be handled together with m_bCancel. while an error
-    // should always also set cancel, cancel doesn't indicate an / set error.
-    bool bNoError = true;
-
     uno::Reference< beans::XPropertySet > xColumnProp;
     {
         // Check for (mandatory) email or (optional) filename column
@@ -1066,7 +1062,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             const sal_Int16 nWantedDBrecords = pSourceDocSh->GetDoc()->GetDocumentFieldsManager().WantedDBrecords();
 
-            m_bCancel = false;
+            m_aMergeStatus = MergeStatus::OK;
 
             SwWrtShell*       pTargetShell = nullptr;
             SwDoc*            pTargetDoc   = nullptr;
@@ -1231,12 +1227,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         if( !aTempFile->IsValid() )
                         {
                             ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
-                            bNoError = false;
-                            m_bCancel = true;
+                            m_aMergeStatus = MergeStatus::ERROR;
                         }
                     }
 
-                    if( !m_bCancel )
+                    if( IsMergeOk() )
                     {
                         std::unique_ptr< INetURLObject > aTempFileURL;
                         if( bNeedsTempFiles )
@@ -1384,12 +1379,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 // some GetPrinter functions have a true default, so keep the false
                                 SfxPrinter* pDocPrt = pWorkView->GetPrinter( false );
                                 JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : pWorkView->GetJobSetup();
-                                m_bCancel = !Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup );
+                                if( !Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup ) )
+                                    MergeCancel();
                             }
-                            if( !m_bCancel && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()))
+                            if( IsMergeOk() && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()) )
                             {
-                                m_bCancel = true;
-                                bNoError = false;
+                                m_aMergeStatus = MergeStatus::ERROR;
                             }
                         }
                         else
@@ -1401,10 +1396,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                               &rMergeDescriptor.aSaveToFilterData, bIsPDFeport,
                                               xWorkDocSh, rWorkShell, &sFileURL ) )
                             {
-                                m_bCancel = true;
-                                bNoError = false;
+                                m_aMergeStatus = MergeStatus::ERROR;
                             }
-                            if( bMT_EMAIL && bNoError )
+                            if( bMT_EMAIL && !IsMergeError() )
                             {
                                 {
                                     SwMailMessage* pMessage = new SwMailMessage;
@@ -1493,7 +1487,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         aLayout->FreezeLayout(true);
                     bFreezedLayouts = true;
                 }
-            } while( !m_bCancel &&
+            } while( IsMergeOk() &&
                 (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
 
             if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
@@ -1512,7 +1506,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     xWorkDocSh->DoClose();
                 }
             }
-            else if( !m_bCancel ) // && bCreateSingleFile
+            else if( IsMergeOk() ) // && bCreateSingleFile
             {
                 RESCHEDULE_GUI;
 
@@ -1531,17 +1525,20 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
                 RESCHEDULE_GUI;
 
-                if( !m_bCancel && bMT_FILE )
+                if( IsMergeOk() && bMT_FILE )
                 {
                     // save merged document
                     assert( aTempFile.get() );
                     INetURLObject aTempFileURL( !rMergeDescriptor.sPath.isEmpty() ?
                                                  rMergeDescriptor.sPath : aTempFile->GetURL() );
-                    bNoError = lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
+                    if( !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
                             pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
-                            bIsPDFeport, xTargetDocShell, *pTargetShell );
+                            bIsPDFeport, xTargetDocShell, *pTargetShell ) )
+                    {
+                        m_aMergeStatus = MergeStatus::ERROR;
+                    }
                 }
-                else if( !m_bCancel && bMT_PRINTER )
+                else if( IsMergeOk() && bMT_PRINTER )
                 {
                     // print the target document
                     uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
@@ -1549,7 +1546,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
                 }
 
-                if( !m_bCancel && bMT_SHELL )
+                if( IsMergeOk() && bMT_SHELL )
                     // leave docshell available for caller (e.g. MM wizard)
                     rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
                 else
@@ -1582,12 +1579,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         xMailDispatcher->shutdown();
     }
 
-    return bNoError;
+    return !IsMergeError();
 }
 
 void SwDBManager::MergeCancel()
 {
-    m_bCancel = true;
+    if (m_aMergeStatus < MergeStatus::CANCEL)
+        m_aMergeStatus = MergeStatus::CANCEL;
 }
 
 IMPL_LINK_TYPED( SwDBManager, PrtCancelHdl, Button *, pButton, void )
commit 9ab2b635eb3411d3191cd3ca1d48b8da5a752d93
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 11 13:49:30 2016 +0100

    MM: cleanup of comments and asserts
    
    Also adds a README to explain some of the code flow of MM.
    
    Change-Id: I363fdd73824a8d41f7073b6de2e9c24184005397

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 6d4ca4c..8ad8ed9 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -144,32 +144,65 @@ struct SwMergeDescriptor
 {
     const DBManagerOptions                              nMergeType;
     SwWrtShell&                                         rSh;
-    const svx::ODataAccessDescriptor&                 rDescriptor;
-    OUString                                            sSaveToFilter; ///< export filter to save resulting files
+    const svx::ODataAccessDescriptor&                   rDescriptor;
+
+    /**
+     * Create a single or multiple results
+     *
+     * This currently just affects FILE and PRINTER, as EMAIL is always
+     * multiple and SHELL is always single.
+     */
+    bool                                                bCreateSingleFile;
+
+    /**
+     * @defgroup save Export filter settings
+     * @addtogroup save
+     * @{ */
+    OUString                                            sSaveToFilter;
     OUString                                            sSaveToFilterOptions;
     css::uno::Sequence< css::beans::PropertyValue >     aSaveToFilterData;
+    /** @} */
 
+    /**
+     * @defgroup file Mail merge as File settings
+     * @addtogroup file
+     * @{ */
     OUString                                            sPath;
+    /** @} */
 
+    /**
+     * @defgroup email Mail merge as eMail settings
+     * @addtogroup email
+     * @{ */
     OUString                                            sSubject;
     OUString                                            sMailBody;
     OUString                                            sAttachmentName;
     css::uno::Sequence< OUString >                      aCopiesTo;
     css::uno::Sequence< OUString >                      aBlindCopiesTo;
-
     css::uno::Reference< css::mail::XSmtpService >      xSmtpServer;
+    bool                                                bSendAsHTML;
+    bool                                                bSendAsAttachment;
+    /** @} */
 
-    bool                                            bSendAsHTML;
-    bool                                            bSendAsAttachment;
-
-    bool                                            bPrintAsync;
-    bool                                            bCreateSingleFile;
+    /**
+     * @addtogroup file email
+     * @{ */
 
+    /** DB column to fetch EMail of Filename from
+     */
     OUString                                            sDBcolumn;
 
-    SwMailMergeConfigItem*                              pMailMergeConfigItem;
+    /** @} */
 
-    css::uno::Sequence<  css::beans::PropertyValue >  aPrintOptions;
+    /**
+     * @defgroup print Mail merge to Printer
+     * @addtogroup print
+     * @{ */
+    bool                                                bPrintAsync;
+    css::uno::Sequence<  css::beans::PropertyValue >    aPrintOptions;
+    /** @} */
+
+    SwMailMergeConfigItem*                              pMailMergeConfigItem;
 
     SwMergeDescriptor( const DBManagerOptions nType,
                        SwWrtShell& rShell,
@@ -177,11 +210,11 @@ struct SwMergeDescriptor
         nMergeType(nType),
         rSh(rShell),
         rDescriptor(rDesc),
+        bCreateSingleFile( false ),
         bSendAsHTML( true ),
         bSendAsAttachment( false ),
         bPrintAsync( false ),
-        bCreateSingleFile( false ),
-        pMailMergeConfigItem(nullptr)
+        pMailMergeConfigItem( nullptr )
     {
         if( nType == DBMGR_MERGE_SHELL )
             bCreateSingleFile = true;
@@ -197,7 +230,14 @@ class SW_DLLPUBLIC SwDBManager
 {
 friend class SwConnectionDisposedListener_Impl;
 
-    bool            m_bCancel;            ///< Mail merge canceled.
+    /** Mail merge cancel indicator
+
+       TODO: convert m_bCancel to a three state escalating enum
+       run, cancel, error. Not sure if this helps readability /
+       further code cleanup, but it would be easier to follow the
+       seamantics and we could get rid of bNoError in MergeMailFiles
+     */
+    bool            m_bCancel;
     bool            bInitDBFields : 1;
     bool            bInMerge    : 1;    ///< merge process active
     bool            bMergeSilent : 1;   ///< suppress display of dialogs/boxes (used when called over API)
@@ -223,7 +263,7 @@ friend class SwConnectionDisposedListener_Impl;
     /// Insert a single data record as text into document.
     SAL_DLLPRIVATE void ImportDBEntry(SwWrtShell* pSh);
 
-    /// merge to file _and_ merge to e-Mail
+    /// Run the mail merge for defined modes, except DBMGR_MERGE
     SAL_DLLPRIVATE bool MergeMailFiles( SwWrtShell* pSh,
                                         const SwMergeDescriptor& rMergeDescriptor,
                                         vcl::Window* pParent );
diff --git a/sw/source/uibase/dbui/README b/sw/source/uibase/dbui/README
new file mode 100644
index 0000000..111ed4af
--- /dev/null
+++ b/sw/source/uibase/dbui/README
@@ -0,0 +1,48 @@
+Mail merge (MM) has *four modes*. The modes 1-3 are directly exposed to the
+user via different GUIs. The modes are:
+
+1. FILE    = saves the result as documents
+2. PRINTER = directly printes resulting documents
+3. EMAIL   = sends results as inidividual emails
+4. SHELL   = returns an internal document shell for further programming
+
+There is one property, which changes the overall behaviour of these modes:
+*bCreateSingleFile*. This is the primary controller of the mail merge source
+code workflow, as it affects all modes!
+
+This also has timing contraints: for individual files the result can be
+defined in advance, while further processing of the single result can just
+be done after the merging. It mainly affects printing and the generation
+of huge (1000+ datasets) combined non-PRINT merge results. A valid
+combined document has to follow contraints, which are already met by
+individual documents, as these are just modified copies.
+
+LO currently has six working combinations of mode and *bCreateSingleFile*
+The others, ''EMAIL+true'' and ''SHELL+false'', are currently not
+implemented. But the list contains implementation proposals for both.
+
+* Mode: FILE
+** false: Saves each merged document as an individual file. The file name can
+   be selected from a database column!
+** true: Saves a combined file of concated documents. Each document starts
+   with a new / reset page style. Depending on the page style this inserts
+   hidden blank pages
+* Mode: PRINTER
+** false: Generates indivividual print jobs, which may be grouped on some 
+   platforms for easier abortion (needs verification!). All print options
+   affect only the individual document! Printing starts after the first
+   document is generated.
+** true: Generates a single print job. All print options affect the combined
+   document! This especially effects the results of reverse and N-UP printing.
+   Printing can just start after all documents are generated.
+* Mode: EMAIL
+** false: Each document can either be used as the email body (html or txt) or
+   be attached to a general email text. The emails are extracted from a DB
+   column, which must be provided! 
+** true: *not implemented*. Could send the combined document to a single
+   email address.
+* Mode: SHELL
+** false: *not implemented*. Instead of a single shell this could return a
+   sequence of shells for the individual documents.
+** true: Returns the shell of the generated document. This is mainly
+   interesting for programmers. The document is just generated internally.
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 367e167..08716c2 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -417,7 +417,7 @@ static bool lcl_GetColumnCnt(SwDSParam* pParam, const OUString& rColumnName,
 // import data
 bool SwDBManager::MergeNew( const SwMergeDescriptor& rMergeDesc, vcl::Window* pParent )
 {
-    OSL_ENSURE(!bInMerge && !pImpl->pMergeData, "merge already activated!");
+    assert( !bInMerge && !pImpl->pMergeData && "merge already activated!" );
 
     SwDBData aData;
     aData.nCommandType = sdb::CommandType::TABLE;
@@ -933,6 +933,10 @@ static void lcl_PreparePrinterOptions(
     }
 }
 
+/**
+ * Please have a look at the README in the same directory, before you make
+ * larger changes in this function!
+ */
 bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                  const SwMergeDescriptor& rMergeDescriptor,
                                  vcl::Window* pParent)
@@ -977,6 +981,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     OUString                            sMailBodyMimeType;
     rtl_TextEncoding                    sMailEncoding = ::osl_getThreadTextEncoding();
 
+    // bNoError should be handled together with m_bCancel. while an error
+    // should always also set cancel, cancel doesn't indicate an / set error.
     bool bNoError = true;
 
     uno::Reference< beans::XPropertySet > xColumnProp;
@@ -1026,7 +1032,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             uno::Reference<document::XDocumentPropertiesSupplier>
                 xDPS(pSourceDocSh->GetModel(), uno::UNO_QUERY);
             xSourceDocProps.set(xDPS->getDocumentProperties());
-            OSL_ENSURE(xSourceDocProps.is(), "DocumentProperties is null");
+            assert( xSourceDocProps.is() && "DocumentProperties is null" );
         }
 
         if( !bMT_SHELL && pSourceDocSh->IsModified() )
@@ -1078,6 +1084,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             if( !IsMergeSilent() )
             {
+                // construct the process dialog
                 pSourceWindow = &pSourceShell->GetView().GetEditWin();
                 if( ! pParent )
                     pParent = pSourceWindow;
@@ -1131,15 +1138,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 // #i72517#
                 const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
                 const SwFrameFormat& rMaster = pSourcePageDesc->GetMaster();
-                bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
+                bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
                                                 rMaster.GetFooter().IsActive();
 
                 // copy compatibility options
-                pTargetShell->GetDoc()->ReplaceCompatibilityOptions( *pSourceShell->GetDoc());
+                pTargetDoc->ReplaceCompatibilityOptions( *pSourceShell->GetDoc() );
                 // #72821# copy dynamic defaults
-                pTargetShell->GetDoc()->ReplaceDefaults( *pSourceShell->GetDoc());
-
-                pTargetShell->GetDoc()->ReplaceDocumentProperties( *pSourceShell->GetDoc());
+                pTargetDoc->ReplaceDefaults( *pSourceShell->GetDoc() );
+                pTargetDoc->ReplaceDocumentProperties( *pSourceShell->GetDoc() );
             }
 
             // Progress, to prohibit KeyInputs
@@ -1167,10 +1173,11 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             long nStartRow, nEndRow;
             bool bFreezedLayouts = false;
-            // collect temporary files
+            // to collect temporary email files
             ::std::vector< OUString> aFilesToRemove;
 
-            // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
+            // The SfxObjectShell will be closed explicitly later but
+            // it is more safe to use SfxObjectShellLock here
             SfxObjectShellLock xWorkDocSh;
             SwView*            pWorkView             = nullptr;
             SwDoc*             pWorkDoc              = nullptr;
@@ -1304,12 +1311,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             pEvtSrc->LaunchMailMergeEvent( aEvt );
                         }
 
-                        if(bCreateSingleFile)
+                        // working copy is merged - prepare final steps depending on merge options
+
+                        if( bCreateSingleFile )
                         {
-                            pWorkDoc->RemoveInvisibleContent();
+                            assert( pTargetShell && "no target shell available!" );
+
+                            // prepare working copy and target to append
 
-                            OSL_ENSURE( pTargetShell, "no target shell available!" );
-                            // copy created file into the target document
+                            pWorkDoc->RemoveInvisibleContent();
                             rWorkShell.ConvertFieldsToText();
                             rWorkShell.SetNumberingRestart();
                             if( bSynchronizedDoc )
@@ -1317,15 +1327,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 lcl_RemoveSectionLinks( rWorkShell );
                             }
 
-                            // insert the document into the target document
-
-                            //#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(nullptr);
-                            if(bPageStylesWithHeaderFooter)
+                            // #i72517# put the styles to the target document
+                            // if the source uses headers or footers each working document
+                            // needs inidividual page styles
+                            SwPageDesc* pTargetPageDesc = nullptr;
+                            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
+                                // 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 );
                                 pTargetPageDesc = pTargetDoc->MakePageDesc( sNewPageDescName );
                                 const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
@@ -1340,16 +1350,19 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             else
                                 pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc );
 
-                            // insert the document into the target document
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
+
+                            // append the working document to the target document
                             if( targetDocPageCount % 2 == 1 )
                                 ++targetDocPageCount; // Docs always start on odd pages (so offset must be even).
                             SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(),
                                 nStartingPageNo, pTargetPageDesc, !bWorkDocInitialized, targetDocPageCount);
                             targetDocPageCount += rWorkShell.GetPageCnt();
+
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
+
                             if (bMT_SHELL)
                             {
                                 SwDocMergeInfo aMergeInfo;
@@ -1419,7 +1432,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                             //read in the temporary file and use it as mail body
                                             SfxMedium aMedium( sFileURL, StreamMode::READ);
                                             SvStream* pInStream = aMedium.GetInStream();
-                                            OSL_ENSURE(pInStream, "no output file created?");
+                                            assert( pInStream && "no output file created?" );
                                             if(pInStream)
                                             {
                                                 pInStream->SetStreamCharSet( sMailEncoding );
@@ -1454,7 +1467,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                     }
                                     xMailDispatcher->enqueueMailMessage( xMessage );
                                     if(!xMailDispatcher->isStarted())
-                                            xMailDispatcher->start();
+                                        xMailDispatcher->start();
                                     //schedule for removal
                                     aFilesToRemove.push_back(sFileURL);
                                 }
@@ -1868,7 +1881,7 @@ OUString SwDBManager::GetDBField(uno::Reference<beans::XPropertySet> xColumnProp
 {
     uno::Reference< sdb::XColumn > xColumn(xColumnProps, uno::UNO_QUERY);
     OUString sRet;
-    OSL_ENSURE(xColumn.is(), "SwDBManager::::ImportDBField: illegal arguments");
+    assert( xColumn.is() && "SwDBManager::::ImportDBField: illegal arguments" );
     if(!xColumn.is())
         return sRet;
 
@@ -2216,7 +2229,8 @@ bool SwDBManager::ExistsNextRecord() const
 sal_uInt32  SwDBManager::GetSelectedRecordId()
 {
     sal_uInt32  nRet = 0;
-    OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
+    assert( pImpl->pMergeData &&
+            pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
     if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is())
         return 0;
     try
@@ -2231,7 +2245,8 @@ sal_uInt32  SwDBManager::GetSelectedRecordId()
 
 bool SwDBManager::ToRecordId(sal_Int32 nSet)
 {
-    OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
+    assert( pImpl->pMergeData &&
+            pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
     if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()|| nSet < 0)
         return false;
     bool bRet = false;
@@ -2826,7 +2841,7 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
         pFound = FindDSConnection(sDataSource, true);
     }
     SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
-    OSL_ENSURE(pFact, "Dialog creation failed!");
+    assert( pFact && "Factory creation failed!" );
     pImpl->pMergeDialog = pFact->CreateMailMergeDlg( DLG_MAILMERGE,
                                                         &rSh.GetView().GetViewFrame()->GetWindow(), rSh,
                                                         sDataSource,
@@ -2834,7 +2849,7 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
                                                         nCmdType,
                                                         xConnection,
                                                         bWithDataSourceBrowser ? nullptr : &aSelection);
-    OSL_ENSURE(pImpl->pMergeDialog, "Dialog creation failed!");
+    assert( pImpl->pMergeDialog && "Dialog creation failed!" );
     if(pImpl->pMergeDialog->Execute() == RET_OK)
     {
         aDescriptor[svx::daSelection] <<= pImpl->pMergeDialog->GetSelection();
@@ -2855,7 +2870,6 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
                         SwDocShell::Factory().GetFilterContainer() );
             try
             {
-
                 uno::Sequence< beans::PropertyValue > aValues(1);
                 beans::PropertyValue* pValues = aValues.getArray();
                 pValues[0].Name = "FilterName";
@@ -2994,13 +3008,12 @@ void SwDBManager::InsertText(SwWrtShell& rSh,
     aDBData.nCommandType = nCmdType;
 
     SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
-    OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
-
+    assert( pFact && "Factory creation failed!" );
     std::unique_ptr<AbstractSwInsertDBColAutoPilot> pDlg(pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(),
                                                                                 xSource,
                                                                                 xColSupp,
                                                                                 aDBData ));
-    OSL_ENSURE(pDlg, "Dialog creation failed!");
+    assert( pDlg && "Dialog creation failed!" );
     if( RET_OK == pDlg->Execute() )
     {
         OUString sDummy;
commit 4667ead7ec18e99066c9551899a3373274adbd3b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Jan 11 13:45:02 2016 +0100

    MM: a failing print job is an error
    
    Change-Id: I0476d0084d6f7e70b123dbb25927822053ca4e1a

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index a8f4833..367e167 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1374,7 +1374,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 m_bCancel = !Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup );
                             }
                             if( !m_bCancel && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()))
+                            {
                                 m_bCancel = true;
+                                bNoError = false;
+                            }
                         }
                         else
                         {
commit ded4dbc027f83d564c540f025e464b4b7c3352e3
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 21:24:46 2016 +0100

    MM: don't send email if document generation failed
    
    Change-Id: I91d13d0694c0586a2dbc159f7ba9d53086b6746c

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index d0da04e..a8f4833 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1388,7 +1388,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 m_bCancel = true;
                                 bNoError = false;
                             }
-                            if( bMT_EMAIL )
+                            if( bMT_EMAIL && bNoError )
                             {
                                 {
                                     SwMailMessage* pMessage = new SwMailMessage;
commit 590787a06e40332cb82f768c3808d57902923389
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 18:51:54 2016 +0100

    MM: some assertion on MM input
    
    Change-Id: Id29ede49acf86ad6109eab88fbae5d9bbb2d8720

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index a73bdcd..6d4ca4c 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -182,8 +182,10 @@ struct SwMergeDescriptor
         bPrintAsync( false ),
         bCreateSingleFile( false ),
         pMailMergeConfigItem(nullptr)
-        {}
-
+    {
+        if( nType == DBMGR_MERGE_SHELL )
+            bCreateSingleFile = true;
+    }
 };
 
 struct SwDBManager_Impl;
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6498baa..d0da04e 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -947,7 +947,19 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     //check if the doc is synchronized and contains at least one linked section
     const bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFormatCount() > 1;
     const bool bNeedsTempFiles = ( bMT_EMAIL || bMT_FILE );
-    const bool bCreateSingleFile = rMergeDescriptor.bCreateSingleFile;
+
+    bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile;
+    if( bMT_EMAIL )
+    {
+        assert( bMT_EMAIL && !bCheckSingleFile_ );
+        bCheckSingleFile_ = false;
+    }
+    else if( bMT_SHELL )
+    {
+        assert( bMT_SHELL && bCheckSingleFile_ );
+        bCheckSingleFile_ = true;
+    }
+    const bool bCreateSingleFile = bCheckSingleFile_;
 
     // Setup for dumping debugging documents
     static const char *sMaxDumpDocs = nullptr;
commit d2590506d1d3e625219640c68e47aa83f547d701
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 18:22:04 2016 +0100

    MM: abort email MM without an email DB column
    
    Change-Id: Ia35a64d08f47af577426749712fa37c3b3b0b6e6

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 2c9e79f..6498baa 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -949,12 +949,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     const bool bNeedsTempFiles = ( bMT_EMAIL || bMT_FILE );
     const bool bCreateSingleFile = rMergeDescriptor.bCreateSingleFile;
 
-    ::rtl::Reference< MailDispatcher >          xMailDispatcher;
-    OUString sMailBodyMimeType;
-    rtl_TextEncoding sMailEncoding = ::osl_getThreadTextEncoding();
-
-    bool bNoError = true;
-
     // Setup for dumping debugging documents
     static const char *sMaxDumpDocs = nullptr;
     static sal_Int32 nMaxDumpDocs = 0;
@@ -967,27 +961,23 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             nMaxDumpDocs = rtl_ustr_toInt32(reinterpret_cast<const sal_Unicode*>( sMaxDumpDocs ), 10);
     }
 
-    if( bMT_EMAIL )
-    {
-        xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
-        if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
-        {
-            sMailBodyMimeType = "text/html; charset=";
-            sMailBodyMimeType += OUString::createFromAscii(
-                    rtl_getBestMimeCharsetFromTextEncoding( sMailEncoding ));
-            SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
-            sMailEncoding = rHtmlOptions.GetTextEncoding();
-        }
-        else
-            sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed";
-    }
+    ::rtl::Reference< MailDispatcher >  xMailDispatcher;
+    OUString                            sMailBodyMimeType;
+    rtl_TextEncoding                    sMailEncoding = ::osl_getThreadTextEncoding();
+
+    bool bNoError = true;
 
     uno::Reference< beans::XPropertySet > xColumnProp;
     {
         // Check for (mandatory) email or (optional) filename column
         SwDBFormatData aColumnDBFormat;
         bool bColumnName = !rMergeDescriptor.sDBcolumn.isEmpty();
-        if( bColumnName )
+        if( ! bColumnName )
+        {
+            if( bMT_EMAIL )
+                return false;
+        }
+        else
         {
             uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
             uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
@@ -998,6 +988,21 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             aColumnDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
             aColumnDBFormat.aNullDate  = pImpl->pMergeData->aNullDate;
+
+            if( bMT_EMAIL )
+            {
+                xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
+                if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
+                {
+                    sMailBodyMimeType = "text/html; charset=";
+                    sMailBodyMimeType += OUString::createFromAscii(
+                                        rtl_getBestMimeCharsetFromTextEncoding( sMailEncoding ));
+                    SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
+                    sMailEncoding = rHtmlOptions.GetTextEncoding();
+                }
+                else
+                    sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed";
+            }
         }
 
         // Try saving the source document
commit 62bbbb83ba437a0b2c46df8a8244eed3822607f1
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 17:13:30 2016 +0100

    MM: move email subject and address into descriptor
    
    Both are not related to the DBManager, but the mail merge job.
    
    While at it, also drop the insane bSubjectIsFilename handling, add
    an independent sPath and rename sAddressFromColumn to a more general
    sDBcolumn, as it's also used for file name lookup in FILE mode.
    
    Change-Id: I1b583f4a67279a229329ba7cd15fb8d2c215737c

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 3ee1aa7..a73bdcd 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -149,8 +149,9 @@ struct SwMergeDescriptor
     OUString                                            sSaveToFilterOptions;
     css::uno::Sequence< css::beans::PropertyValue >     aSaveToFilterData;
 
+    OUString                                            sPath;
+
     OUString                                            sSubject;
-    OUString                                            sAddressFromColumn;
     OUString                                            sMailBody;
     OUString                                            sAttachmentName;
     css::uno::Sequence< OUString >                      aCopiesTo;
@@ -163,7 +164,8 @@ struct SwMergeDescriptor
 
     bool                                            bPrintAsync;
     bool                                            bCreateSingleFile;
-    bool                                            bSubjectIsFilename;
+
+    OUString                                            sDBcolumn;
 
     SwMailMergeConfigItem*                              pMailMergeConfigItem;
 
@@ -179,7 +181,6 @@ struct SwMergeDescriptor
         bSendAsAttachment( false ),
         bPrintAsync( false ),
         bCreateSingleFile( false ),
-        bSubjectIsFilename( false ),
         pMailMergeConfigItem(nullptr)
         {}
 
@@ -194,8 +195,6 @@ class SW_DLLPUBLIC SwDBManager
 {
 friend class SwConnectionDisposedListener_Impl;
 
-    OUString            sEMailAddrField;      ///< Mailing: Column name of email address.
-    OUString            sSubject;           ///< Mailing: Subject
     bool            m_bCancel;            ///< Mail merge canceled.
     bool            bInitDBFields : 1;
     bool            bInMerge    : 1;    ///< merge process active
@@ -259,10 +258,6 @@ public:
     inline bool     IsInitDBFields() const  { return bInitDBFields; }
     inline void     SetInitDBFields(bool b) { bInitDBFields = b;    }
 
-    /// Mailing: Set email data.
-    inline void     SetEMailColumn(const OUString& sColName) { sEMailAddrField = sColName; }
-    inline void     SetSubject(const OUString& sSbj) { sSubject = sSbj; }
-
     /// Fill listbox with all table names of a database.
     bool            GetTableNames(ListBox* pListBox, const OUString& rDBName );
 
diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx
index 6fd3e80..a99cb9c 100644
--- a/sw/inc/swabstdlg.hxx
+++ b/sw/inc/swabstdlg.hxx
@@ -149,7 +149,7 @@ public:
     virtual bool IsSaveSingleDoc() const = 0;
     virtual bool IsGenerateFromDataBase() const = 0;
     virtual OUString GetColumnName() const = 0;
-    virtual OUString GetPath() const = 0;
+    virtual OUString GetPath(bool) const = 0;
 
 };
 class AbstractMailMergeCreateFromDlg : public VclAbstractDialog
diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx
index a097e03..1a6d47b 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -511,9 +511,9 @@ OUString AbstractMailMergeDlg_Impl::GetColumnName() const
     return pDlg->GetColumnName();
 }
 
-OUString AbstractMailMergeDlg_Impl::GetPath() const
+OUString AbstractMailMergeDlg_Impl::GetPath(bool user) const
 {
-    return pDlg->GetPath();
+    return pDlg->GetPath(user);
 }
 
 bool AbstractMailMergeCreateFromDlg_Impl::IsThisDocument() const
diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx
index 45690eb..98af687 100644
--- a/sw/source/ui/dialog/swdlgfact.hxx
+++ b/sw/source/ui/dialog/swdlgfact.hxx
@@ -284,7 +284,7 @@ class AbstractMailMergeDlg_Impl : public AbstractMailMergeDlg
     virtual bool IsSaveSingleDoc() const override;
     virtual bool IsGenerateFromDataBase() const override;
     virtual OUString GetColumnName() const override;
-    virtual OUString GetPath() const override;
+    virtual OUString GetPath(bool) const override;
 };
 
 class SwMailMergeCreateFromDlg;
diff --git a/sw/source/ui/envelp/mailmrge.cxx b/sw/source/ui/envelp/mailmrge.cxx
index 5f55838..107d8a7 100644
--- a/sw/source/ui/envelp/mailmrge.cxx
+++ b/sw/source/ui/envelp/mailmrge.cxx
@@ -491,7 +491,6 @@ bool SwMailMergeDlg::ExecQryShell()
     if(pImpl->xSelSupp.is()) {
         pImpl->xSelSupp->removeSelectionChangeListener(  pImpl->xChgLstnr );
     }
-    SwDBManager* pMgr = rSh.GetDBManager();
 
     if (m_pPrinterRB->IsChecked())
         nMergeType = DBMGR_MERGE_PRINTER;
@@ -501,33 +500,27 @@ bool SwMailMergeDlg::ExecQryShell()
         INetURLObject aAbs;
         if( pMedium )
             aAbs = pMedium->GetURLObject();
-        OUString sPath(
+        pModOpt->SetMailingPath(
             URIHelper::SmartRel2Abs(
                 aAbs, m_pPathED->GetText(), URIHelper::GetMaybeFileHdl()));
-        pModOpt->SetMailingPath(sPath);
-
-        if (!sPath.endsWith("/"))
-            sPath += "/";
 
         pModOpt->SetIsNameFromColumn(m_pGenerateFromDataBaseCB->IsChecked());
 
-        if (m_pGenerateFromDataBaseCB->IsEnabled() && m_pGenerateFromDataBaseCB->IsChecked()) {
-            pMgr->SetEMailColumn(m_pColumnLB->GetSelectEntry());
+        if (!AskUserFilename()) {
             pModOpt->SetNameFromColumn(m_pColumnLB->GetSelectEntry());
             if( m_pFilterLB->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND)
                 m_sSaveFilter = *static_cast<const OUString*>(m_pFilterLB->GetSelectEntryData());
+            m_sFilename = OUString();
         } else {
             //#i97667# reset column name - otherwise it's remembered from the last run
-            pMgr->SetEMailColumn(OUString());
+            pModOpt->SetNameFromColumn(OUString());
             //start save as dialog
             OUString sFilter;
-            sPath = SwMailMergeHelper::CallSaveAsDialog(sFilter);
-            if (sPath.isEmpty())
+            m_sFilename = SwMailMergeHelper::CallSaveAsDialog(sFilter);
+            if (m_sFilename.isEmpty())
                 return false;
             m_sSaveFilter = sFilter;
         }
-
-        pMgr->SetSubject(sPath);
     }
 
     if (m_pFromRB->IsChecked()) {  // Insert list
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 05e27d0..2c9e79f 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -986,14 +986,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     {
         // Check for (mandatory) email or (optional) filename column
         SwDBFormatData aColumnDBFormat;
-        bool bColumnName = !sEMailAddrField.isEmpty();
+        bool bColumnName = !rMergeDescriptor.sDBcolumn.isEmpty();
         if( bColumnName )
         {
             uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
             uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
-            if(!xCols->hasByName(sEMailAddrField))
+            if( !xCols->hasByName( rMergeDescriptor.sDBcolumn ) )
                 return false;
-            uno::Any aCol = xCols->getByName(sEMailAddrField);
+            uno::Any aCol = xCols->getByName( rMergeDescriptor.sDBcolumn );
             aCol >>= xColumnProp;
 
             aColumnDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
@@ -1164,7 +1164,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             {
                 nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
                 {
-                    OUString sPath(sSubject);
+                    OUString sPath = rMergeDescriptor.sPath;
                     OUString sColumnData;
 
                     // Read the indicated data column, which should contain a valid mail
@@ -1204,8 +1204,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         OUString sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
                         aTempFile.reset(
                             new utl::TempFile(sLeading, true, &sExt, &sPath));
-                        if( rMergeDescriptor.bSubjectIsFilename )
-                            aTempFile->EnableKillingFile();
                         if( !aTempFile->IsValid() )
                         {
                             ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
@@ -1504,7 +1502,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 {
                     // save merged document
                     assert( aTempFile.get() );
-                    INetURLObject aTempFileURL( rMergeDescriptor.bSubjectIsFilename ? sSubject : aTempFile->GetURL());
+                    INetURLObject aTempFileURL( !rMergeDescriptor.sPath.isEmpty() ?
+                                                 rMergeDescriptor.sPath : aTempFile->GetURL() );
                     bNoError = lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
                             pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
                             bIsPDFeport, xTargetDocShell, *pTargetShell );
@@ -2872,12 +2871,11 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
 
                     SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
                     aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
-                    aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc() && pImpl->pMergeDialog->GetMergeType() != DBMGR_MERGE_PRINTER;
-                    aMergeDesc.bSubjectIsFilename = aMergeDesc.bCreateSingleFile;
+                    aMergeDesc.bCreateSingleFile = pImpl->pMergeDialog->IsSaveSingleDoc();
+                    aMergeDesc.sPath = pImpl->pMergeDialog->GetPath(true);
                     if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() )
                     {
-                        aMergeDesc.sAddressFromColumn = pImpl->pMergeDialog->GetColumnName();
-                        aMergeDesc.sSubject = pImpl->pMergeDialog->GetPath();
+                        aMergeDesc.sDBcolumn = pImpl->pMergeDialog->GetColumnName();
                     }
 
                     MergeNew(aMergeDesc);
diff --git a/sw/source/uibase/inc/mailmrge.hxx b/sw/source/uibase/inc/mailmrge.hxx
index f4d1aae..0630347 100644
--- a/sw/source/uibase/inc/mailmrge.hxx
+++ b/sw/source/uibase/inc/mailmrge.hxx
@@ -103,6 +103,7 @@ class SwMailMergeDlg : public SvxStandardDialog
 
     Size            m_aDialogSize;
     OUString m_sSaveFilter;
+    OUString m_sFilename;
 
     DECL_LINK_TYPED( ButtonHdl, Button*, void );
     DECL_LINK_TYPED( InsertPathHdl, Button*, void );
@@ -113,6 +114,8 @@ class SwMailMergeDlg : public SvxStandardDialog
 
     virtual void    Apply() override;
     bool            ExecQryShell();
+    bool            AskUserFilename() const
+    { return (m_pSaveSingleDocRB->IsChecked() || !m_pGenerateFromDataBaseCB->IsChecked()); }
 
 public:
     SwMailMergeDlg(vcl::Window* pParent, SwWrtShell& rSh,
@@ -129,7 +132,13 @@ public:
     bool IsSaveSingleDoc() const { return m_pSaveSingleDocRB->IsChecked(); }
     bool IsGenerateFromDataBase() const { return m_pGenerateFromDataBaseCB->IsChecked(); }
     OUString GetColumnName() const { return m_pColumnLB->GetSelectEntry();}
-    OUString GetPath() const { return m_pPathED->GetText();}
+    OUString GetPath(bool user=false) const
+    {
+        if( user && AskUserFilename() )
+            return m_sFilename;
+        return m_pPathED->GetText();
+    }
+    const OUString& GetFilename() const { return m_sFilename; }
 
     const OUString& GetSaveFilter() const {return m_sSaveFilter;}

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list