[Libreoffice-commits] core.git: Branch 'private/jmux/mm-cleanup' - 200 commits - accessibility/inc accessibility/source android/source avmedia/source basctl/source basic/source bin/update_pch bin/update_pch_autotune.sh bin/update_pch_bisect bridges/source bridges/test canvas/source chart2/source cli_ure/qa cli_ure/readme.txt cli_ure/source codemaker/source comphelper/qa comphelper/source compilerplugins/clang config.guess config_host/config_clang.h.in config_host.mk.in configmgr/source configure.ac connectivity/source cppcanvas/source cppu/source cui/source cui/uiconfig dbaccess/qa dbaccess/source desktop/source dictionaries drawinglayer/source dtrans/source dtrans/test editeng/source embeddedobj/source embeddedobj/test embedserv/source extensions/source extensions/test extensions/workben external/icu external/redland external/unixODBC filter/qa filter/source forms/qa forms/source formula/source fpicker/source framework/inc framework/JunitTest_framework_complex.mk framework/qa framework/source g helpcompiler/source helpcontent2 hwpfilter/source i18nlangtag/source i18npool/source icon-themes/industrial include/basegfx include/basic include/comphelper include/connectivity include/cppuhelper include/drawinglayer include/editeng include/formula include/i18nlangtag include/jvmfwk include/o3tl include/oox include/osl include/registry include/rsc include/rtl include/sfx2 include/svl include/svtools include/svx include/tools include/ucbhelper include/uno include/unotools include/vcl include/xmloff ios/CustomTarget_Lo_Xcconfig.mk io/source ios/README io/test jurt/com jvmfwk/source l10ntools/source libreofficekit/qa libreofficekit/README lingucomponent/source linguistic/source lotuswordpro/source Makefile.fetch mysqlc/source nlpsolver/ThirdParty o3tl/qa odk/docs odk/examples odk/index.html odk/index_online.html offapi/com offapi/type_reference officecfg/registry onlineupdate/source oox/source package/source pyuno/qa pyuno/source qadevOOo/runner qadevOOo/tests readlicense_oo/docs read license_oo/Module_readlicense_oo.mk readlicense_oo/Package_readlicense_oo_readmes.mk registry/source registry/tools reportdesign/inc reportdesign/source rsc/source sal/inc sal/osl sal/qa sal/workben sax/source sc/inc sc/qa scripting/examples scripting/java scripting/source sc/source sdext/source sd/qa sd/source setup_native/source sfx2/inc sfx2/source sfx2/uiconfig shell/source solenv/bin solenv/doc solenv/gbuild solenv/inc soltools/cpp sot/source starmath/inc starmath/source stoc/source stoc/test svgio/source svl/source svl/unx svtools/source svx/source swext/mediawiki sw/inc sw/ooxmlexport_setup.mk sw/qa sw/sdi sw/source sysui/desktop test/source testtools/qa testtools/source toolkit/qa toolkit/source toolkit/test tools/source ucbhelper/source ucb/qa ucb/source udkapi/com unotest/source unotools/source unoxml/source vcl/android vcl/CustomTarget_afm_hash.mk vcl/generic vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/null vcl/opengl vcl/osx vcl/Package_opengl_blacklist.mk vcl/qa vcl/quartz vcl/README.lifecycle vcl/source vcl/unx vcl/win vcl/workben winaccessibility/inc winaccessibility/source wizards/com wizards/source writerfilter/documentation writerfilter/inc writerfilter/source xmerge/source xmlhelp/source xmloff/dtd xmloff/inc xmloff/source xmlscript/test xmlsecurity/inc xmlsecurity/source

Jan-Marek Glogowski glogow at fbihome.de
Mon Jan 11 06:39:41 PST 2016


Rebased ref, commits from common ancestor:
commit 694a25cb100f1233ee8667a97f4d2a1c942a0d4a
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 5c8dce6..e900af0 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,
                                         const 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 d82a93f..d3a4d1a 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -404,7 +404,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;
@@ -944,6 +944,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,
                                  const vcl::Window* pParent)
@@ -1007,6 +1011,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;
@@ -1056,7 +1062,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() )
@@ -1108,6 +1114,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             if( !IsMergeSilent() )
             {
+                // construct the process dialog
                 pSourceWindow = &pSourceShell->GetView().GetEditWin();
                 vcl::Window* pRealParent = nullptr;
                 if( ! pParent )
@@ -1162,15 +1169,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
@@ -1198,10 +1204,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;
@@ -1335,12 +1342,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 )
@@ -1348,15 +1358,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 );
@@ -1453,7 +1463,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 );
@@ -1488,7 +1498,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                     }
                                     xMailDispatcher->enqueueMailMessage( xMessage );
                                     if(!xMailDispatcher->isStarted())
-                                            xMailDispatcher->start();
+                                        xMailDispatcher->start();
                                     //schedule for removal
                                     aFilesToRemove.push_back(sFileURL);
                                 }
@@ -1907,7 +1917,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;
 
@@ -2251,7 +2261,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
@@ -2266,7 +2277,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;
@@ -2861,7 +2873,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,
@@ -2869,7 +2881,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();
@@ -2890,7 +2902,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";
@@ -3029,13 +3040,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 94240417dbd0c8b59ebf10e9e73cf71e074a6f66
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 6b67129..d82a93f 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1408,7 +1408,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 #endif
                             }
                             if( !m_bCancel && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()))
+                            {
                                 m_bCancel = true;
+                                bNoError = false;
+                            }
                         }
                         else
                         {
commit 2695ca673eb4e785a66b0035a10bbf532ad1268d
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 ab1a848..6b67129 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1422,7 +1422,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 m_bCancel = true;
                                 bNoError = false;
                             }
-                            if( bMT_EMAIL )
+                            if( bMT_EMAIL && bNoError )
                             {
                                 {
                                     SwMailMessage* pMessage = new SwMailMessage;
commit 9acae4992c944216e2813b3803f68df758e982c8
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 a4501cc..5c8dce6 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 5b1bb8e..ab1a848 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -979,6 +979,16 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         bCheckSingleFile_ = true;
 #endif
     }
+    else 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
commit 39418933627a0d95a243541ab4c9de263b28ecc6
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 18:22:04 2016 +0100

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

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index d0490e9..5b1bb8e 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -981,12 +981,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     }
     const bool bCreateSingleFile = bCheckSingleFile_;
 
-    ::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;
@@ -999,27 +993,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();
@@ -1030,6 +1020,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 a7b4cd42c3906d151d455d031fe530959fb605b1
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 3a47409..a4501cc 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
@@ -260,10 +259,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 2808c4e..d0490e9 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1018,14 +1018,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;
@@ -1197,7 +1197,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
@@ -1237,8 +1237,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 );
@@ -1545,7 +1543,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 );
@@ -2909,12 +2908,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;}
     inline const css::uno::Sequence< css::uno::Any > GetSelection() const { return m_aSelection; }
diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx
index f8ff1a5..839adae 100644
--- a/sw/source/uibase/uno/unomailmerge.cxx
+++ b/sw/source/uibase/uno/unomailmerge.cxx
@@ -700,7 +700,6 @@ uno::Any SAL_CALL SwXMailMerge::execute(
         aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get();
         break;
     case MailMergeType::FILE:
-    case MailMergeType::MAIL:
         {
             INetURLObject aURLObj;
             aURLObj.SetSmartProtocol( INetProtocol::File );
@@ -731,23 +730,22 @@ uno::Any SAL_CALL SwXMailMerge::execute(
             if (!aPath.isEmpty() && !aPath.endsWith(aDelim))
                 aPath += aDelim;
             if (bCurFileNameFromColumn)
-                pMgr->SetEMailColumn( aCurFileNamePrefix );
+                aMergeDesc.sDBcolumn = aCurFileNamePrefix;
             else
             {
                 aPath += aCurFileNamePrefix;
-                pMgr->SetEMailColumn( OUString() );
-            }
-            pMgr->SetSubject( aPath );
-            if(MailMergeType::FILE == nCurOutputType)
-            {
-                aMergeDesc.sSaveToFilter = m_sSaveFilter;
-                aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions;
-                aMergeDesc.aSaveToFilterData = m_aSaveFilterData;
-                aMergeDesc.bCreateSingleFile = m_bSaveAsSingleFile;
             }
-            else
+
+            aMergeDesc.sPath = aPath;
+            aMergeDesc.sSaveToFilter = m_sSaveFilter;
+            aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions;
+            aMergeDesc.aSaveToFilterData = m_aSaveFilterData;
+            aMergeDesc.bCreateSingleFile = m_bSaveAsSingleFile;
+        }
+        break;
+    case MailMergeType::MAIL:
             {
-                pMgr->SetEMailColumn( m_sAddressFromColumn );
+                aMergeDesc.sDBcolumn = m_sAddressFromColumn;
                 if(m_sAddressFromColumn.isEmpty())
                     throw RuntimeException("Mail address column not set.", static_cast < cppu::OWeakObject * > ( this ) );
                 aMergeDesc.sSaveToFilter     = m_sAttachmentFilter;
@@ -769,7 +767,6 @@ uno::Any SAL_CALL SwXMailMerge::execute(
                 if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected())
                     throw RuntimeException("Failed to connect to mail server.", static_cast < cppu::OWeakObject * > ( this ) );
             }
-        }
         break;
     }
 
commit e50c4d7abdb92d41fbe4bbcc3833b8151d76ae5d
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 11:18:00 2016 +0100

    MM: don't generate documents for invalid emails
    
    If we don't have a valid mail address, there is no point merging a
    document. But now the first document is probably skipped, so all
    the setup has to be handled differently.
    
    We also have to account differently for documents with fields of
    type RES_DBNEXTSETFLD or RES_DBNUMSETFLD, as these would advance
    the document cursor for multiple rows.
    
    Sadly there is currently no way to inform the user of bad email
    entries. As before these entries are just skipped.
    
    Change-Id: I2b02174e173b8b721c7394d47febfefd3b3066e9

diff --git a/sw/inc/IDocumentFieldsAccess.hxx b/sw/inc/IDocumentFieldsAccess.hxx
index d573e76..89222fc 100644
--- a/sw/inc/IDocumentFieldsAccess.hxx
+++ b/sw/inc/IDocumentFieldsAccess.hxx
@@ -106,6 +106,16 @@ namespace com { namespace sun { namespace star { namespace uno { class Any; } }
 
     virtual SwDocUpdateField& GetUpdateFields() const = 0;
 
+    /* How many DB records are needed to fill the document
+
+       Counts the fields, which advance the DB cursor, + 1.
+       Result is always > 0, as even a document without fields will
+       advance the cursor in mail merge.
+
+       @return amount of needed DB records
+     */
+    virtual sal_uInt16 WantedDBrecords() const = 0;
+
     /*  @@@MAINTAINABILITY-HORROR@@@
         SwNode (see parameter pChk) is (?) part of the private
         data structure of SwDoc and should not be exposed
diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index c7b4f95..3a47409 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -325,7 +325,7 @@ public:
                                       OUString &rResult, double *pNumber);
     bool            FillCalcWithMergeData(SvNumberFormatter *pDocFormatter,
                                           sal_uInt16 nLanguage, bool asString, SwCalc &aCalc);
-    bool            ToNextMergeRecord();
+    bool            ToNextMergeRecord(const sal_uInt16 nSkip = 0);
     bool            ToNextRecord(const OUString& rDataSource, const OUString& rTableOrQuery, sal_Int32 nCommandType = -1);
 
     bool            ExistsNextRecord()const;
diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx b/sw/source/core/doc/DocumentFieldsManager.cxx
index 7180489..b54fee8 100644
--- a/sw/source/core/doc/DocumentFieldsManager.cxx
+++ b/sw/source/core/doc/DocumentFieldsManager.cxx
@@ -829,6 +829,23 @@ void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt )
     delete pCalc;
 }
 
+sal_uInt16 DocumentFieldsManager::WantedDBrecords() const
+{
+    sal_uInt16 nMaxDBrecods = 1;
+    sal_uInt16 aTypes[2] = { RES_DBNEXTSETFLD, RES_DBNUMSETFLD };
+
+    for( sal_uInt16 n = 0; n < 2; ++n )
+    {
+        SwFieldType* pFieldType = GetSysFieldType( aTypes[ n ] );
+        SwIterator<SwFormatField,SwFieldType> aIter( *pFieldType );
+        for( const SwFormatField* pFormatField = aIter.First();
+                pFormatField; pFormatField = aIter.Next() )
+            nMaxDBrecods++;
+    }
+
+    return nMaxDBrecods;
+}
+
 void DocumentFieldsManager::UpdateExpFields( SwTextField* pUpdateField, bool bUpdRefFields )
 {
     if( IsExpFieldsLocked() || m_rDoc.IsInReading() )
diff --git a/sw/source/core/inc/DocumentFieldsManager.hxx b/sw/source/core/inc/DocumentFieldsManager.hxx
index 4c05c29..5c3d7df 100644
--- a/sw/source/core/inc/DocumentFieldsManager.hxx
+++ b/sw/source/core/inc/DocumentFieldsManager.hxx
@@ -54,6 +54,7 @@ public:
     virtual void UnlockExpFields() override;
     virtual bool IsExpFieldsLocked() const override;
     virtual SwDocUpdateField& GetUpdateFields() const override;
+    virtual sal_uInt16 WantedDBrecords() const override;
     virtual bool SetFieldsDirty(bool b, const SwNode* pChk, sal_uLong nLen) override;
     virtual void SetFixFields(bool bOnlyTimeDate, const DateTime* pNewDateTime) override;
     virtual void FieldsToCalc(SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt) override;
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 9e1fe10..2808c4e 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -135,6 +135,7 @@
 #include <ndtxt.hxx>
 #include <calc.hxx>
 #include <dbfld.hxx>
+#include <DocumentFieldsManager.hxx>
 
 #include <memory>
 #include <config_cups.h>
@@ -169,7 +170,8 @@ const sal_Char cActiveConnection[] = "ActiveConnection";
     } while( 0 )
 
 enum class SwDBNextRecord { NEXT, FIRST };
-static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action = SwDBNextRecord::NEXT );
+static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip = 0,
+                              const SwDBNextRecord action = SwDBNextRecord::NEXT );
 
 static bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<sdbc::XResultSet>& xResultSet )
 {
@@ -459,7 +461,7 @@ bool SwDBManager::MergeNew( const SwMergeDescriptor& rMergeDesc, vcl::Window* pP
         pImpl->pMergeData->xConnection = xConnection;
     // add an XEventListener
 
-    lcl_ToNextRecord(pImpl->pMergeData, SwDBNextRecord::FIRST);
+    lcl_ToNextRecord(pImpl->pMergeData, 0, SwDBNextRecord::FIRST);
 
     uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,aData.sDataSource);
 
@@ -1014,9 +1016,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
     uno::Reference< beans::XPropertySet > xColumnProp;
     {
+        // Check for (mandatory) email or (optional) filename column
+        SwDBFormatData aColumnDBFormat;
         bool bColumnName = !sEMailAddrField.isEmpty();
-
-        if (bColumnName)
+        if( bColumnName )
         {
             uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, uno::UNO_QUERY );
             uno::Reference<container::XNameAccess> xCols = xColsSupp->getColumns();
@@ -1024,6 +1027,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 return false;
             uno::Any aCol = xCols->getByName(sEMailAddrField);
             aCol >>= xColumnProp;
+
+            aColumnDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
+            aColumnDBFormat.aNullDate  = pImpl->pMergeData->aNullDate;
         }
 
         // Try saving the source document
@@ -1067,6 +1073,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             }
             const bool bIsPDFeport = pStoreToFilter && pStoreToFilter->GetFilterName() == "writer_pdf_Export";
 
+            const sal_Int16 nWantedDBrecords = pSourceDocSh->GetDoc()->GetDocumentFieldsManager().WantedDBrecords();
+
             m_bCancel = false;
 
             SwWrtShell*       pTargetShell = nullptr;
@@ -1183,33 +1191,45 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             SwView*            pWorkView             = nullptr;
             SwDoc*             pWorkDoc              = nullptr;
             SwDBManager*       pWorkDocOrigDBManager = nullptr;
+            bool               bWorkDocInitialized   = false;
 
             do
             {
                 nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
                 {
                     OUString sPath(sSubject);
+                    OUString sColumnData;
 
-                    OUString sAddress;
-                    if( !bMT_EMAIL && bColumnName )
+                    // Read the indicated data column, which should contain a valid mail
+                    // address or an optional file name
+                    if( bMT_EMAIL )
+                    {
+                        sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
+                        if( !SwMailMergeHelper::CheckMailAddress( sColumnData ) )
+                        {
+                            OSL_FAIL("invalid e-Mail address in database column");
+                            nDocNo++;
+                            ToNextMergeRecord(nWantedDBrecords);
+                            nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
+                            continue;
+                        }
+                    }
+                    else if( bColumnName )
                     {
-                        SwDBFormatData aDBFormat;
-                        aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
-                        aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
-                        sAddress = GetDBField( xColumnProp, aDBFormat);
-                        if (sAddress.isEmpty())
-                            sAddress = "_";
-                        sPath += sAddress;
+                        sColumnData = GetDBField( xColumnProp, aColumnDBFormat );
+                        if (sColumnData.isEmpty())
+                            sColumnData = "_";
+                        sPath += sColumnData;
                     }
 
                     // create a new temporary file name - only done once in case of bCreateSingleFile
-                    if( bNeedsTempFiles && ( 1 == nDocNo || !bCreateSingleFile ))
+                    if( bNeedsTempFiles && ( !bWorkDocInitialized || !bCreateSingleFile ))
                     {
                         INetURLObject aEntry(sPath);
                         OUString sLeading;
                         //#i97667# if the name is from a database field then it will be used _as is_
-                        if( !sAddress.isEmpty() )
-                            sLeading = sAddress;
+                        if( !sColumnData.isEmpty() )
+                            sLeading = sColumnData;
                         else
                             sLeading = aEntry.GetBase();
                         aEntry.removeSegment();
@@ -1251,7 +1271,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         // Create a copy of the source document and work with that one instead of the source.
                         // If we're not in the single file mode (which requires modifying the document for the merging),
                         // it is enough to do this just once. Currently PDF also has to be treated special.
-                        if( 1 == nDocNo || bCreateSingleFile || bIsPDFeport )
+                        if( !bWorkDocInitialized || bCreateSingleFile || bIsPDFeport )
                         {
                             assert( !xWorkDocSh.Is());
                             // copy the source document
@@ -1344,7 +1364,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, nDocNo == 1, targetDocPageCount);
+                                nStartingPageNo, pTargetPageDesc, !bWorkDocInitialized, targetDocPageCount);
                             targetDocPageCount += rWorkShell.GetPageCnt();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
@@ -1360,8 +1380,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         }
                         else if( bMT_PRINTER )
                         {
-                            assert(!bCreateSingleFile);
-                            if( 1 == nDocNo ) // set up printing only once at the beginning
+                            if( !bWorkDocInitialized ) // set up printing only once at the beginning
                             {
                                 uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
                                 lcl_PreparePrinterOptions( rMergeDescriptor.aPrintOptions, false, aOptions );
@@ -1392,23 +1411,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             }
                             if( bMT_EMAIL )
                             {
-                                SwDBFormatData aDBFormat;
-                                aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
-                                aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
-                                OUString sMailAddress = GetDBField( xColumnProp, aDBFormat);
-                                if(!SwMailMergeHelper::CheckMailAddress( sMailAddress ))
-                                {
-                                    OSL_FAIL("invalid e-Mail address in database column");
-                                }
-                                else
                                 {
                                     SwMailMessage* pMessage = new SwMailMessage;
                                     uno::Reference< mail::XMailMessage > xMessage = pMessage;
                                     if(rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo())
                                         pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo());
-                                    pMessage->addRecipient( sMailAddress );
+                                    pMessage->addRecipient( sColumnData );
                                     pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() );
                                     OUString sBody;
+
                                     if(rMergeDescriptor.bSendAsAttachment)
                                     {
                                         sBody = rMergeDescriptor.sMailBody;
@@ -1475,6 +1486,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         }
                     }
                 }
+                bWorkDocInitialized = true;
                 nDocNo++;
                 nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
 
@@ -2046,10 +2058,10 @@ bool    SwDBManager::GetMergeColumnCnt(const OUString& rColumnName, sal_uInt16 n
     return bRet;
 }
 
-bool SwDBManager::ToNextMergeRecord()
+bool SwDBManager::ToNextMergeRecord( const sal_uInt16 nSkip )
 {
     assert( pImpl->pMergeData && pImpl->pMergeData->xResultSet.is() && "no data source in merge" );
-    return lcl_ToNextRecord( pImpl->pMergeData );
+    return lcl_ToNextRecord( pImpl->pMergeData, nSkip );
 }
 
 bool SwDBManager::FillCalcWithMergeData( SvNumberFormatter *pDocFormatter,
@@ -2144,7 +2156,7 @@ bool SwDBManager::ToNextRecord(
     return lcl_ToNextRecord( pFound );
 }
 
-static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action )
+static bool lcl_ToNextRecord( SwDSParam* pParam, const sal_uInt16 nSkip, const SwDBNextRecord action )
 {
     bool bRet = true;
 
@@ -2170,7 +2182,8 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action )
         if( pParam->aSelection.getLength() )
         {
             sal_Int32 nPos = 0;
-            pParam->aSelection.getConstArray()[ pParam->nSelectionIndex++ ] >>= nPos;
+            pParam->aSelection.getConstArray()[ pParam->nSelectionIndex ] >>= nPos;
+            pParam->nSelectionIndex += 1 + nSkip;
             pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
             bRet = !pParam->bEndOfDB;
             if( pParam->nSelectionIndex >= pParam->aSelection.getLength() )
@@ -2178,19 +2191,25 @@ static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action )
         }
         else if( action == SwDBNextRecord::FIRST )
         {
-            pParam->bEndOfDB = !pParam->xResultSet->first();
+            if( 0 == nSkip )
+                pParam->bEndOfDB = !pParam->xResultSet->first();
+            else
+                pParam->bEndOfDB = !pParam->xResultSet->absolute( nSkip );
         }
         else
         {
             sal_Int32 nBefore = pParam->xResultSet->getRow();
-            pParam->bEndOfDB = !pParam->xResultSet->next();
+            if( 0 == nSkip )
+                pParam->bEndOfDB = !pParam->xResultSet->next();
+            else
+                pParam->bEndOfDB = !pParam->xResultSet->absolute( nBefore + nSkip );
             if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow() )
             {
                 // next returned true but it didn't move
                 pParam->bEndOfDB = true;
             }
             bRet = !pParam->bEndOfDB;
-            ++pParam->nSelectionIndex;
+            pParam->nSelectionIndex += 1 + nSkip;
         }
         // always update pParam from bEndOfDB setting
         pParam->CheckEndOfDB();
commit d576b9a3b1f474ecadf09d1b16f18b8fc3bc3141
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 13:26:23 2016 +0100

    MM: cleanup single file case finish
    
    Took me a while to realize most of the post-mm code actually depends
    on bCreateSingleFile. This allows us to simplify the code structure.
    
    Change-Id: Ifd8a8a882d9902bedd40c8b1d1e4a8507b5877fe

diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 0af593e..9e1fe10 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -1510,50 +1510,35 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     xWorkDocSh->DoClose();
                 }
             }
-
-            if (bCreateSingleFile)
+            else if( !m_bCancel ) // && bCreateSingleFile
             {
+                RESCHEDULE_GUI;
+
                 // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate
                 // unique fly names, do it here once.
                 pTargetDoc->SetInMailMerge(false);
                 pTargetDoc->SetAllUniqueFlyNames();
-            }
-
-            RESCHEDULE_GUI;
 
-            // Unfreeze target document layouts and correct all PageDescs.
-            if(bCreateSingleFile)
-            {
+                // Unfreeze target document layouts and correct all PageDescs.
                 pTargetShell->CalcLayout();
                 for ( auto aLayout : pTargetShell->GetDoc()->GetAllLayouts() )
                 {
                     aLayout->FreezeLayout(false);
                     aLayout->AllCheckPageDescs();
                 }
-            }
 
-            pProgressDlg.disposeAndClear();
+                RESCHEDULE_GUI;
 
-            // save the single output document
-            if( bMT_SHELL )
-            {
-                rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
-            }
-            else if(bCreateSingleFile)
-            {
-                if( bMT_PRINTER )
+                if( !m_bCancel && bMT_FILE )
                 {
-                    if( !m_bCancel )
-                    {
-                        // save merged document
-                        assert( aTempFile.get() );
-                        INetURLObject aTempFileURL( rMergeDescriptor.bSubjectIsFilename ? sSubject : aTempFile->GetURL());
-                        bNoError = !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
-                                pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
-                                bIsPDFeport, xTargetDocShell, *pTargetShell );
-                    }
+                    // save merged document
+                    assert( aTempFile.get() );
+                    INetURLObject aTempFileURL( rMergeDescriptor.bSubjectIsFilename ? sSubject : aTempFile->GetURL());
+                    bNoError = !lcl_SaveDoc( &aTempFileURL, pStoreToFilter,
+                            pStoreToFilterOptions, &rMergeDescriptor.aSaveToFilterData,
+                            bIsPDFeport, xTargetDocShell, *pTargetShell );
                 }
-                else if( pTargetView ) // must be available!
+                else if( !m_bCancel && bMT_PRINTER )
                 {
                     // print the target document
                     uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
@@ -1561,12 +1546,16 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
                 }
 
-                // Leave docshell available for caller (e.g. MM wizard)
-                if( !bMT_SHELL )
+                if( !m_bCancel && bMT_SHELL )
+                    // leave docshell available for caller (e.g. MM wizard)
+                    rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
+                else
                     xTargetDocShell->DoClose();
             }
 
-            //remove the temporary files
+            pProgressDlg.disposeAndClear();
+
+            // remove the temporary files
             ::std::vector<OUString>::iterator aFileIter;
             for(aFileIter = aFilesToRemove.begin();
                         aFileIter != aFilesToRemove.end(); ++aFileIter)
commit 610a9d48384315197e1e59f48a46862b0e10853c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 09:54:11 2016 +0100

    MM: rename and constify variables
    
    Instead of the huge comparisons (in terms of text space), this
    deconstructs the mail merge type into smaller uppercase variables.
    
    bCancel is renamed to m_bCancel to especially distinguish it from
    the bNoError local variable, as both are supposed to be handled
    together.
    
    Otherall this should improve the readability of the code.
    
    Change-Id: I51ab17f7cd90a9e195d09dfcf37a0d194aa9fbbd

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index e3a6120..c7b4f95 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -142,7 +142,7 @@ typedef std::vector<std::unique_ptr<SwDSParam>> SwDSParams_t;
 
 struct SwMergeDescriptor
 {
-    DBManagerOptions                                    nMergeType;
+    const DBManagerOptions                              nMergeType;
     SwWrtShell&                                         rSh;
     const svx::ODataAccessDescriptor&                 rDescriptor;
     OUString                                            sSaveToFilter; ///< export filter to save resulting files
@@ -169,7 +169,9 @@ struct SwMergeDescriptor
 
     css::uno::Sequence<  css::beans::PropertyValue >  aPrintOptions;
 
-    SwMergeDescriptor( DBManagerOptions nType, SwWrtShell& rShell, svx::ODataAccessDescriptor& rDesc ) :
+    SwMergeDescriptor( const DBManagerOptions nType,
+                       SwWrtShell& rShell,
+                       const svx::ODataAccessDescriptor& rDesc ) :
         nMergeType(nType),
         rSh(rShell),
         rDescriptor(rDesc),
@@ -194,7 +196,7 @@ friend class SwConnectionDisposedListener_Impl;
 
     OUString            sEMailAddrField;      ///< Mailing: Column name of email address.
     OUString            sSubject;           ///< Mailing: Subject
-    bool            bCancel;            ///< Mail merge canceled.
+    bool            m_bCancel;            ///< Mail merge canceled.
     bool            bInitDBFields : 1;
     bool            bInMerge    : 1;    ///< merge process active
     bool            bMergeSilent : 1;   ///< suppress display of dialogs/boxes (used when called over API)
@@ -221,8 +223,9 @@ friend class SwConnectionDisposedListener_Impl;
     SAL_DLLPRIVATE void ImportDBEntry(SwWrtShell* pSh);
 
     /// merge to file _and_ merge to e-Mail
-    SAL_DLLPRIVATE bool          MergeMailFiles(SwWrtShell* pSh,
-                                        const SwMergeDescriptor& rMergeDescriptor, vcl::Window* pParent );
+    SAL_DLLPRIVATE bool MergeMailFiles( SwWrtShell* pSh,
+                                        const SwMergeDescriptor& rMergeDescriptor,
+                                        const vcl::Window* pParent );
 
     SwDBManager(SwDBManager const&) = delete;
     SwDBManager& operator=(SwDBManager const&) = delete;
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6ce8c0f..0af593e 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -762,7 +762,7 @@ void SwDBManager::GetColumnNames(ListBox* pListBox,
 }
 
 SwDBManager::SwDBManager(SwDoc* pDoc)
-    : bCancel(false)
+    : m_bCancel(false)
     , bInitDBFields(false)
     , bInMerge(false)
     , bMergeSilent(false)
@@ -944,16 +944,21 @@ static void lcl_PreparePrinterOptions(
 
 bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                  const SwMergeDescriptor& rMergeDescriptor,
-                                 vcl::Window* pParent)
+                                 const vcl::Window* pParent)
 {
+    // deconstruct mail merge type for better readability.
+    // uppercase naming is intentional!
+    const bool bMT_EMAIL   = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL;
+    const bool bMT_SHELL   = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL;
+    const bool bMT_PRINTER = rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER;
+    const bool bMT_FILE    = rMergeDescriptor.nMergeType == DBMGR_MERGE_FILE;
+
+    const bool bNeedsTempFiles = ( bMT_EMAIL || bMT_FILE );
     //check if the doc is synchronized and contains at least one linked section
-    bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFormatCount() > 1;
-    bool bNoError = true;
-    const bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL;
-    const bool bMergeShell = rMergeDescriptor.nMergeType == DBMGR_MERGE_SHELL;
-    bool bCreateSingleFile = rMergeDescriptor.bCreateSingleFile;
+    const bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFormatCount() > 1;
 
-    if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER )
+    bool bCheckSingleFile_ = rMergeDescriptor.bCreateSingleFile;
+    if( bMT_PRINTER )
     {
         // It is possible to do MM printing in both modes for the same result, but the singlefile mode
         // is slower because of all the temporary document copies and merging them together
@@ -967,16 +972,20 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         // to use the faster mode. As I have no idea about other platforms, keep them using
         // the slower singlefile mode (or feel free to check them, or rewrite the printing code).
 #if ENABLE_CUPS && !defined(MACOSX)
-        bCreateSingleFile = !psp::PrinterInfoManager::get().supportsBatchPrint();
+        bCheckSingleFile_ = !psp::PrinterInfoManager::get().supportsBatchPrint();
 #else
-        bCreateSingleFile = true;
+        bCheckSingleFile_ = true;
 #endif
     }
+    const bool bCreateSingleFile = bCheckSingleFile_;
 
     ::rtl::Reference< MailDispatcher >          xMailDispatcher;
-    OUString sBodyMimeType;
-    rtl_TextEncoding eEncoding = ::osl_getThreadTextEncoding();
+    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;
     if (!sMaxDumpDocs)
@@ -988,19 +997,19 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             nMaxDumpDocs = rtl_ustr_toInt32(reinterpret_cast<const sal_Unicode*>( sMaxDumpDocs ), 10);
     }
 
-    if(bEMail)
+    if( bMT_EMAIL )
     {
         xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
         if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
         {
-            sBodyMimeType = "text/html; charset=";
-            sBodyMimeType += OUString::createFromAscii(
-                                rtl_getBestMimeCharsetFromTextEncoding( eEncoding ));
+            sMailBodyMimeType = "text/html; charset=";
+            sMailBodyMimeType += OUString::createFromAscii(
+                    rtl_getBestMimeCharsetFromTextEncoding( sMailEncoding ));
             SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
-            eEncoding = rHtmlOptions.GetTextEncoding();
+            sMailEncoding = rHtmlOptions.GetTextEncoding();
         }
         else
-            sBodyMimeType = "text/plain; charset=UTF-8; format=flowed";
+            sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed";
     }
 
     uno::Reference< beans::XPropertySet > xColumnProp;
@@ -1029,17 +1038,18 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             OSL_ENSURE(xSourceDocProps.is(), "DocumentProperties is null");
         }
 
-        if( !bMergeShell && pSourceDocSh->IsModified() )
+        if( !bMT_SHELL && pSourceDocSh->IsModified() )
             pSfxDispatcher->Execute( pSourceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SfxCallMode::SYNCHRON|SfxCallMode::RECORD);
-        if( bMergeShell || !pSourceDocSh->IsModified() )
+        if( bMT_SHELL || !pSourceDocSh->IsModified() )
         {
+            // setup the output format
             const SfxFilter* pStoreToFilter = SwIoSystem::GetFileFilter(
                 pSourceDocSh->GetMedium()->GetURLObject().GetMainURL(INetURLObject::NO_DECODE));
             SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer();
             const OUString* pStoreToFilterOptions = nullptr;
 
             // if a save_to filter is set then use it - otherwise use the default
-            if( bEMail && !rMergeDescriptor.bSendAsAttachment )
+            if( bMT_EMAIL && !rMergeDescriptor.bSendAsAttachment )
             {
                 OUString sExtension = rMergeDescriptor.bSendAsHTML ? OUString("html") : OUString("txt");
                 pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SfxFilterFlags::EXPORT);
@@ -1057,17 +1067,14 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             }
             const bool bIsPDFeport = pStoreToFilter && pStoreToFilter->GetFilterName() == "writer_pdf_Export";
 
-            bCancel = false;
-
-            // in case of creating a single resulting file this has to be created here
-            SwWrtShell* pTargetShell = nullptr;
-            SwDoc* pTargetDoc = nullptr;
+            m_bCancel = false;
 
+            SwWrtShell*       pTargetShell = nullptr;
+            SwDoc*            pTargetDoc   = nullptr;
+            SwView*           pTargetView  = nullptr;
             SfxObjectShellRef xTargetDocShell;
 
-            SwView* pTargetView = nullptr;
             std::unique_ptr< utl::TempFile > aTempFile;
-            bool createTempFile = ( rMergeDescriptor.nMergeType == DBMGR_MERGE_EMAIL || rMergeDescriptor.nMergeType == DBMGR_MERGE_FILE );
             OUString sModifiedStartingPageDesc;
             OUString sStartingPageDesc;
             sal_uInt16 nStartingPageNo = 0;
@@ -1076,15 +1083,21 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             vcl::Window *pSourceWindow = nullptr;
             VclPtr<CancelableDialog> pProgressDlg;
 
-            if (!IsMergeSilent()) {
+            if( !IsMergeSilent() )
+            {
                 pSourceWindow = &pSourceShell->GetView().GetEditWin();
+                vcl::Window* pRealParent = nullptr;
                 if( ! pParent )
-                    pParent = pSourceWindow;
-                if( bMergeShell )
-                    pProgressDlg = VclPtr<CreateMonitor>::Create( pParent, pParent != pSourceWindow );
+                    pRealParent = pSourceWindow;
+                if( bMT_SHELL )
+                    pProgressDlg = VclPtr<CreateMonitor>::Create(
+                        pRealParent, pRealParent != pSourceWindow );
                 else {
-                    pProgressDlg = VclPtr<PrintMonitor>::Create( pParent, pParent != pSourceWindow, PrintMonitor::MONITOR_TYPE_PRINT );
-                    static_cast<PrintMonitor*>( pProgressDlg.get() )->SetText(pSourceShell->GetView().GetDocShell()->GetTitle(22));
+                    pProgressDlg = VclPtr<PrintMonitor>::Create(
+                        pRealParent, pRealParent != pSourceWindow,
+                        PrintMonitor::MONITOR_TYPE_PRINT );
+                    static_cast<PrintMonitor*>( pProgressDlg.get() )->SetText(
+                        pSourceShell->GetView().GetDocShell()->GetTitle(22) );
                 }
                 pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
                 pProgressDlg->Show();
@@ -1092,7 +1105,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 RESCHEDULE_GUI;
             }
 
-            if(bCreateSingleFile)
+            if( bCreateSingleFile )
             {
                 // create a target docshell to put the merged document into
                 xTargetDocShell = new SwDocShell( SfxObjectCreateMode::STANDARD );
@@ -1100,7 +1113,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 if (nMaxDumpDocs)
                     lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
                 SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
-                if (bMergeShell && pSourceWindow) {
+                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());
@@ -1156,7 +1169,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             // it can be manually computed from the source documents (for which we do layouts, so the page
             // count is known, and there is a blank page between each of them in the target document).
             int targetDocPageCount = 0;
-            if( !IsMergeSilent() && bMergeShell &&
+            if( !IsMergeSilent() && bMT_SHELL &&
                     lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) )
                 static_cast<CreateMonitor*>( pProgressDlg.get() )->SetTotalCount( nDocCount );
 
@@ -1167,10 +1180,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
             SfxObjectShellLock xWorkDocSh;
-            // a view frame for the document
-            SwView* pWorkView = nullptr;
-            SwDoc* pWorkDoc = nullptr;
-            SwDBManager* pOldDBManager = nullptr;
+            SwView*            pWorkView             = nullptr;
+            SwDoc*             pWorkDoc              = nullptr;
+            SwDBManager*       pWorkDocOrigDBManager = nullptr;
 
             do
             {
@@ -1179,7 +1191,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     OUString sPath(sSubject);
 
                     OUString sAddress;
-                    if( !bEMail && bColumnName )
+                    if( !bMT_EMAIL && bColumnName )
                     {
                         SwDBFormatData aDBFormat;
                         aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
@@ -1191,7 +1203,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                     }
 
                     // create a new temporary file name - only done once in case of bCreateSingleFile
-                    if( createTempFile && ( 1 == nDocNo || !bCreateSingleFile ))
+                    if( bNeedsTempFiles && ( 1 == nDocNo || !bCreateSingleFile ))
                     {
                         INetURLObject aEntry(sPath);
                         OUString sLeading;
@@ -1211,22 +1223,22 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         {
                             ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
                             bNoError = false;
-                            bCancel = true;
+                            m_bCancel = true;
                         }
                     }
 
-                    if( !bCancel )
+                    if( !m_bCancel )
                     {
                         std::unique_ptr< INetURLObject > aTempFileURL;
-                        if( createTempFile )
+                        if( bNeedsTempFiles )
                             aTempFileURL.reset( new INetURLObject(aTempFile->GetURL()));
                         if (!IsMergeSilent()) {
-                            if( bMergeShell )
+                            if( bMT_SHELL )
                                 static_cast<CreateMonitor*>( pProgressDlg.get() )->SetCurrentPosition( nDocNo );
                             else {
                                 PrintMonitor *pPrintMonDlg = static_cast<PrintMonitor*>( pProgressDlg.get() );
-                                pPrintMonDlg->m_pPrinter->SetText( createTempFile ? aTempFileURL->GetBase() : OUString( pSourceDocSh->GetTitle( 22 )));
-                                OUString sStat(SW_RES(STR_STATSTR_LETTER));   // Brief
+                                pPrintMonDlg->m_pPrinter->SetText( bNeedsTempFiles ? aTempFileURL->GetBase() : OUString( pSourceDocSh->GetTitle( 22 )));
+                                OUString sStat(SW_RES(STR_STATSTR_LETTER));
                                 sStat += " ";
                                 sStat += OUString::number( nDocNo );
                                 pPrintMonDlg->m_pPrintInfo->SetText( sStat );
@@ -1238,7 +1250,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
                         // Create a copy of the source document and work with that one instead of the source.
                         // If we're not in the single file mode (which requires modifying the document for the merging),
-                        // it is enough to do this just once.
+                        // it is enough to do this just once. Currently PDF also has to be treated special.
                         if( 1 == nDocNo || bCreateSingleFile || bIsPDFeport )
                         {
                             assert( !xWorkDocSh.Is());
@@ -1255,7 +1267,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             pWorkDoc->ReplaceDocumentProperties( *pSourceDocSh->GetDoc());
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
-                            pOldDBManager = pWorkDoc->GetDBManager();
+                            pWorkDocOrigDBManager = pWorkDoc->GetDBManager();
                             pWorkDoc->SetDBManager( this );
                             pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
 
@@ -1336,7 +1348,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             targetDocPageCount += rWorkShell.GetPageCnt();
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
                                 lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
-                            if (bMergeShell)
+                            if (bMT_SHELL)
                             {
                                 SwDocMergeInfo aMergeInfo;
                                 // Name of the mark is actually irrelevant, UNO bookmarks have internals names.
@@ -1346,7 +1358,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo );
                             }
                         }
-                        else if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER )
+                        else if( bMT_PRINTER )
                         {
                             assert(!bCreateSingleFile);
                             if( 1 == nDocNo ) // set up printing only once at the beginning
@@ -1357,28 +1369,28 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                 pWorkView->StartPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
                                 SfxPrinter* pDocPrt = pWorkView->GetPrinter();
                                 JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : SfxViewShell::GetJobSetup();
-                                bCancel = !Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup );
+                                m_bCancel = !Printer::PreparePrintJob( pWorkView->GetPrinterController(), aJobSetup );
 #if ENABLE_CUPS && !defined(MACOSX)
-                                if( !bCancel )
+                                if( !m_bCancel )
                                     psp::PrinterInfoManager::get().startBatchPrint();
 #endif
                             }
-                            if( !bCancel && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()))
-                                bCancel = true;
+                            if( !m_bCancel && !Printer::ExecutePrintJob( pWorkView->GetPrinterController()))
+                                m_bCancel = true;
                         }
                         else
                         {
-                            assert( createTempFile );
+                            assert( bNeedsTempFiles );
                             // save merged document
                             OUString sFileURL;
                             if( lcl_SaveDoc( aTempFileURL.get(), pStoreToFilter, pStoreToFilterOptions,
                                              &rMergeDescriptor.aSaveToFilterData, bIsPDFeport,
                                              xWorkDocSh, rWorkShell, &sFileURL ) )
                             {
-                                bCancel = true;
+                                m_bCancel = true;
                                 bNoError = false;
                             }
-                            if( bEMail )
+                            if( bMT_EMAIL )
                             {
                                 SwDBFormatData aDBFormat;
                                 aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
@@ -1417,12 +1429,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                             OSL_ENSURE(pInStream, "no output file created?");
                                             if(pInStream)
                                             {
-                                                pInStream->SetStreamCharSet( eEncoding );
+                                                pInStream->SetStreamCharSet( sMailEncoding );
                                                 OString sLine;
                                                 bool bDone = pInStream->ReadLine( sLine );
                                                 while ( bDone )
                                                 {
-                                                    sBody += OStringToOUString(sLine, eEncoding);
+                                                    sBody += OStringToOUString( sLine, sMailEncoding );
                                                     sBody += "\n";
                                                     bDone = pInStream->ReadLine( sLine );
                                                 }
@@ -1432,8 +1444,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                     pMessage->setSubject( rMergeDescriptor.sSubject );
                                     uno::Reference< datatransfer::XTransferable> xBody =
                                                 new SwMailTransferable(
-                                                    sBody,
-                                                    sBodyMimeType);
+                                                    sBody, sMailBodyMimeType);
                                     pMessage->setBody( xBody );
 
                                     if(rMergeDescriptor.aCopiesTo.getLength())
@@ -1458,7 +1469,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         }
                         if( bCreateSingleFile || bIsPDFeport )
                         {
-                            pWorkDoc->SetDBManager( pOldDBManager );
+                            pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
                             xWorkDocSh->DoClose();
                             xWorkDocSh = nullptr;
                         }
@@ -1475,7 +1486,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         aLayout->FreezeLayout(true);
                     bFreezedLayouts = true;
                 }
-            } while( !bCancel &&
+            } while( !m_bCancel &&
                 (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
 
             if ( xWorkDocSh.Is() && pWorkView->GetWrtShell().IsExpFieldsLocked() )
@@ -1486,7 +1497,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
             if( !bCreateSingleFile )
             {
-                if( rMergeDescriptor.nMergeType == DBMGR_MERGE_PRINTER )
+                if( bMT_PRINTER )
                 {
                     Printer::FinishPrintJob( pWorkView->GetPrinterController());
 #if ENABLE_CUPS && !defined(MACOSX)
@@ -1495,7 +1506,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 }
                 if( !bIsPDFeport )
                 {
-                    pWorkDoc->SetDBManager( pOldDBManager );
+                    pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
                     xWorkDocSh->DoClose();
                 }
             }
@@ -1524,15 +1535,15 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             pProgressDlg.disposeAndClear();
 
             // save the single output document
-            if (bMergeShell)
+            if( bMT_SHELL )
             {
                 rMergeDescriptor.pMailMergeConfigItem->SetTargetView( pTargetView );
             }
             else if(bCreateSingleFile)
             {
-                if( rMergeDescriptor.nMergeType != DBMGR_MERGE_PRINTER )
+                if( bMT_PRINTER )
                 {
-                    if( !bCancel )
+                    if( !m_bCancel )
                     {
                         // save merged document
                         assert( aTempFile.get() );
@@ -1551,7 +1562,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 }
 
                 // Leave docshell available for caller (e.g. MM wizard)
-                if (!bMergeShell)
+                if( !bMT_SHELL )
                     xTargetDocShell->DoClose();
             }
 
@@ -1573,7 +1584,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         }
     }
 
-    if(bEMail)
+    if( xMailDispatcher.is() )
     {
         xMailDispatcher->stop();
         xMailDispatcher->shutdown();
@@ -1584,7 +1595,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
 
 void SwDBManager::MergeCancel()
 {
-    bCancel = true;
+    m_bCancel = true;
 }
 
 IMPL_LINK_TYPED( SwDBManager, PrtCancelHdl, Button *, pButton, void )
@@ -2885,7 +2896,7 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
                     pView->AttrChangedNotify( &pView->GetWrtShell() );// in order for SelectShell to be called
                     //set the current DBManager
                     SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc();
-                    SwDBManager* pWorkDBManager = pWorkDoc->GetDBManager();
+                    SwDBManager* pWorkDocOrigDBManager = pWorkDoc->GetDBManager();
                     pWorkDoc->SetDBManager( this );
 
                     SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
@@ -2900,7 +2911,7 @@ void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh,
 
                     MergeNew(aMergeDesc);
 
-                    pWorkDoc->SetDBManager( pWorkDBManager );
+                    pWorkDoc->SetDBManager( pWorkDocOrigDBManager );
                     //close the temporary file
                     uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY );
                     if (xClose.is())
commit 64da218a961b1447759c548785c589f481f5ed0e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Jan 8 09:41:55 2016 +0100

    MM: refactor DBManager related duplicated code
    
    Moves the duplicated code for saving documents, configuring the
    printer and DB cursor forwarding (next record) into static local
    functions.
    
    Change-Id: I75f183a2a515ecbae276461613a05ab50c56e600

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index f5b752f..e3a6120 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -223,7 +223,6 @@ friend class SwConnectionDisposedListener_Impl;
     /// merge to file _and_ merge to e-Mail
     SAL_DLLPRIVATE bool          MergeMailFiles(SwWrtShell* pSh,
                                         const SwMergeDescriptor& rMergeDescriptor, vcl::Window* pParent );
-    SAL_DLLPRIVATE bool          ToNextRecord(SwDSParam* pParam);
 
     SwDBManager(SwDBManager const&) = delete;
     SwDBManager& operator=(SwDBManager const&) = delete;
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 3932b11..6ce8c0f 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -158,10 +158,20 @@ const sal_Char cDataSourceName[] = "DataSourceName";
 const sal_Char cSelection[] = "Selection";
 const sal_Char cActiveConnection[] = "ActiveConnection";
 
-namespace
-{
+#define EMIT_SW_EVENT(type, shell) \
+        SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_##type, \
+            SwDocShell::GetEventName(STR_SW_EVENT_##type), shell))
+
+#define RESCHEDULE_GUI \
+    do { \
+        for( sal_uInt16 i = 0; i < 25; i++) \
+            Application::Reschedule(); \
+    } while( 0 )
+
+enum class SwDBNextRecord { NEXT, FIRST };
+static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action = SwDBNextRecord::NEXT );
 
-bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<sdbc::XResultSet>& xResultSet )
+static bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<sdbc::XResultSet>& xResultSet )
 {
     uno::Reference<beans::XPropertySet> xPrSet(xResultSet, uno::UNO_QUERY);
     if(xPrSet.is())
@@ -186,7 +196,6 @@ bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<sdbc::XR
     }
     return false;
 }
-}
 
 class SwConnectionDisposedListener_Impl : public cppu::WeakImplHelper
 < lang::XEventListener >
@@ -450,29 +459,7 @@ bool SwDBManager::MergeNew( const SwMergeDescriptor& rMergeDesc, vcl::Window* pP
         pImpl->pMergeData->xConnection = xConnection;
     // add an XEventListener
 
-    try{
-        //set to start position
-        if(pImpl->pMergeData->aSelection.getLength())
-        {
-            sal_Int32 nPos = 0;
-            pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
-            pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
-            pImpl->pMergeData->CheckEndOfDB();
-            if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
-                pImpl->pMergeData->bEndOfDB = true;
-        }
-        else
-        {
-            pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
-            pImpl->pMergeData->CheckEndOfDB();
-        }
-    }
-    catch (const uno::Exception& e)
-    {
-        pImpl->pMergeData->bEndOfDB = true;
-        pImpl->pMergeData->CheckEndOfDB();
-        SAL_WARN("sw.mailmerge", "exception in MergeNew(): " << e.Message);
-    }
+    lcl_ToNextRecord(pImpl->pMergeData, SwDBNextRecord::FIRST);
 
     uno::Reference<sdbc::XDataSource> xSource = SwDBManager::getDataSourceAsParent(xConnection,aData.sDataSource);
 
@@ -858,8 +845,8 @@ static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
     rWorkShell.SetLabelDoc( false );
 }
 
-static void lcl_SaveDoc( SfxObjectShell *xTargetDocShell,
-                         const char *name, int no = 0 )
+static void lcl_SaveDebugDoc( SfxObjectShell *xTargetDocShell,
+                              const char *name, int no = 0 )
 {
     const OUString sExt( ".odt" );
     OUString basename = OUString::createFromAscii( name );
@@ -878,6 +865,83 @@ static void lcl_SaveDoc( SfxObjectShell *xTargetDocShell,
     delete pDstMed;
 }
 
+static bool lcl_SaveDoc(
+    const INetURLObject* pFileURL,
+    const SfxFilter* pStoreToFilter,
+    const OUString* pStoreToFilterOptions,
+    const uno::Sequence< beans::PropertyValue >* pSaveToFilterData,
+    const bool bIsPDFeport,
+    SfxObjectShell* xObjectShell,
+    SwWrtShell& rWorkShell,
+    OUString * const decodedURL = nullptr )
+{
+    OUString url = pFileURL->GetMainURL( INetURLObject::NO_DECODE );
+    if( decodedURL )
+        (*decodedURL) = url;
+
+    SfxMedium* pDstMed = new SfxMedium( url, STREAM_STD_READWRITE );
+    pDstMed->SetFilter( pStoreToFilter );
+    if( pDstMed->GetItemSet() )
+    {
+        if( pStoreToFilterOptions )
+            pDstMed->GetItemSet()->Put( SfxStringItem(SID_FILE_FILTEROPTIONS,
+                                        *pStoreToFilterOptions));
+        if( pSaveToFilterData->getLength() )
+            pDstMed->GetItemSet()->Put( SfxUsrAnyItem(SID_FILTER_DATA,
+                                        uno::makeAny(*pSaveToFilterData)));
+    }
+
+    // convert fields to text if we are exporting to PDF.
+    // this prevents a second merge while updating the fields
+    // in SwXTextDocument::getRendererCount()
+    if( bIsPDFeport )
+        rWorkShell.ConvertFieldsToText();
+
+    bool bAnyError = !xObjectShell->DoSaveAs(*pDstMed);
+    xObjectShell->DoSaveCompleted(pDstMed);
+    bAnyError = bAnyError || xObjectShell->GetError();
+    if( bAnyError )
+    {
+        // error message ??
+        ErrorHandler::HandleError( xObjectShell->GetError() );
+    }
+    return bAnyError;
+}
+
+static void lcl_PreparePrinterOptions(
+    const uno::Sequence< beans::PropertyValue >& rInPrintOptions,
+    const bool bVisibleMonitor,
+    uno::Sequence< beans::PropertyValue >& rOutPrintOptions)
+{
+    // printing should be done synchronously otherwise the document
+    // might already become invalid during the process
+
+    const sal_Int32 nOffset = !bVisibleMonitor ? 2 : 1;
+    rOutPrintOptions.realloc( nOffset );
+    rOutPrintOptions[ 0 ].Name = "Wait";
+    rOutPrintOptions[ 0 ].Value <<= sal_True;
+    if( !bVisibleMonitor )
+    {
+        rOutPrintOptions[ 1 ].Name = "MonitorVisible";
+        rOutPrintOptions[ 1 ].Value <<= sal_False;
+    }
+
+    // copy print options
+    const beans::PropertyValue* pOptions = rInPrintOptions.getConstArray();
+    for( sal_Int32 n = 0, nIndex = nOffset ; n < rInPrintOptions.getLength(); ++n)
+    {
+        if( pOptions[n].Name == "CopyCount" || pOptions[n].Name == "FileName"
+            || pOptions[n].Name == "Collate" || pOptions[n].Name == "Pages"
+            || pOptions[n].Name == "Wait" || pOptions[n].Name == "PrinterName" )
+        {
+            // add an option
+            rOutPrintOptions.realloc( nIndex + 1 );
+            rOutPrintOptions[ nIndex ].Name = pOptions[n].Name;
+            rOutPrintOptions[ nIndex++ ].Value = pOptions[n].Value ;
+        }
+    }
+}
+
 bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                                  const SwMergeDescriptor& rMergeDescriptor,
                                  vcl::Window* pParent)
@@ -1025,8 +1089,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
                 pProgressDlg->Show();
 
-                for( sal_uInt16 i = 0; i < 25; i++)
-                    Application::Reschedule();
+                RESCHEDULE_GUI;
             }
 
             if(bCreateSingleFile)
@@ -1035,7 +1098,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 xTargetDocShell = new SwDocShell( SfxObjectCreateMode::STANDARD );
                 xTargetDocShell->DoInitNew();
                 if (nMaxDumpDocs)
-                    lcl_SaveDoc( xTargetDocShell, "MergeDoc" );
+                    lcl_SaveDebugDoc( xTargetDocShell, "MergeDoc" );
                 SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
                 if (bMergeShell && pSourceWindow) {
                     //the created window has to be located at the same position as the source window
@@ -1171,9 +1234,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             pProgressDlg->Update();
                         }
 
-                        // Computation time for the GUI
-                        for( sal_uInt16 i = 0; i < 25; i++ )
-                            Application::Reschedule();
+                        RESCHEDULE_GUI;
 
                         // Create a copy of the source document and work with that one instead of the source.
                         // If we're not in the single file mode (which requires modifying the document for the merging),
@@ -1193,7 +1254,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                             pWorkDoc = rWorkShell.GetDoc();
                             pWorkDoc->ReplaceDocumentProperties( *pSourceDocSh->GetDoc());
                             if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) )
-                                lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo );
+                                lcl_SaveDebugDoc( xWorkDocSh, "WorkDoc", nDocNo );
                             pOldDBManager = pWorkDoc->GetDBManager();
                             pWorkDoc->SetDBManager( this );
                             pWorkDoc->getIDocumentLinksAdministration().EmbedAllLinks();
@@ -1206,7 +1267,9 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                         }
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list