officecfg/registry/schema/org/openoffice/Office/Writer.xcs |    6 
 sw/inc/doc.hxx                                             |    1 
 sw/source/core/doc/doc.cxx                                 |  128 +++++++------
 sw/source/core/text/txtfld.cxx                             |   12 -
 4 files changed, 87 insertions(+), 60 deletions(-)

New commits:
commit 75401516fbb3ebb0a571e50bf26501b9ae85dacd
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Oct 25 11:47:56 2023 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Fri Oct 27 11:31:45 2023 +0200

    Simplify a bit
    
    Change-Id: I6b98dd9b383b82c5bcba9235d81b0a9a63a918b2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158430
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158477
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index 004a2bc17c09..f0732a84204a 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -63,14 +63,10 @@ static bool lcl_IsInBody( SwFrame const *pFrame )
 {
     if ( pFrame->IsInDocBody() )
         return true;
-    else
-    {
-        const SwFrame *pTmp = pFrame;
-        const SwFlyFrame *pFly;
-        while ( nullptr != (pFly = pTmp->FindFlyFrame()) )
-            pTmp = pFly->GetAnchorFrame();
-        return pTmp->IsInDocBody();
-    }
+
+    while (const SwFlyFrame* pFly = pFrame->FindFlyFrame())
+        pFrame = pFly->GetAnchorFrame();
+    return pFrame->IsInDocBody();
 }
 
 SwExpandPortion *SwTextFormatter::NewFieldPortion( SwTextFormatInfo &rInf,
commit ef29791179ca6cfcb5c82a65fefcbe29e039831d
Author:     Mike Kaganski <[email protected]>
AuthorDate: Sat Oct 21 17:42:56 2023 +0300
Commit:     Michael Stahl <[email protected]>
CommitDate: Fri Oct 27 11:31:35 2023 +0200

    Related: tdf#89178 Add an option to avoid converting some fields into text
    
    ... during mail merge.
    
    In some modes (generating individual documents; creating PDF) the mail merge
    process converts all fields into text. But sometimes it is undesirable for
    fields not involved into mail merge itself:
    
    * It is inconsistent with how MS Word behaves;
    * The generated editable documents could benefit from having other fields
      kept as fields;
    * Some fields, when exported to PDF, produce different results: e.g.,
      placeholder fields are output as empty spaces, not as placeholder text.
    
    An expert boolean configuration option is added:
    Office/Writer/FormLetter/ConvertToTextOnlyMMFields; it is false by default,
    in which case, the behavior is unchanged. When true, all fields in the mail
    merge document, except for database fields and hidden text fields, are not
    converted to text during mail merge process.
    
    Change-Id: Ibdb505ed3f2762db063bb0a91b674d27ecbc2e7f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158306
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158476
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
index cfa36e974ca8..d09e31d0dbc8 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
@@ -6000,6 +6000,12 @@
           </prop>
         </group>
       </group>
+      <prop oor:name="ConvertToTextOnlyMMFields" oor:type="xs:boolean" 
oor:nillable="false">
+        <info>
+          <desc>When true, only fields that can be used in mail merge will be 
converted to text; all other fields will be kept as fields in the Mail Merge 
output</desc>
+        </info>
+        <value>false</value>
+      </prop>
     </group>
     <group oor:name="Misc">
       <info>
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index a08638d9c625..bbf045188c55 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1445,6 +1445,7 @@ public:
     // restore the invisible content if it's available on the undo stack
     bool RestoreInvisibleContent();
 
+    // Replace fields by text - mailmerge support
     SAL_DLLPRIVATE bool ConvertFieldsToText(SwRootFrame const& rLayout);
 
     // Create sub-documents according to given collection.
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 18d9fa2018ab..e3b606c6916d 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -53,6 +53,8 @@
 #include <editeng/pbinitem.hxx>
 #include <unotools/localedatawrapper.hxx>
 
+#include <officecfg/Office/Writer.hxx>
+
 #include <swatrset.hxx>
 #include <swmodule.hxx>
 #include <fmtrfmrk.hxx>
@@ -1608,12 +1610,32 @@ bool SwDoc::RestoreInvisibleContent()
     return false;
 }
 
+static bool IsMailMergeField(SwFieldIds fieldId)
+{
+    switch (fieldId)
+    {
+        case SwFieldIds::Database: // Mail merge fields
+        case SwFieldIds::DatabaseName: // Database name
+        case SwFieldIds::HiddenText: // Hidden text may use database fields in 
condition
+        case SwFieldIds::HiddenPara: // Hidden paragraph may use database 
fields in condition
+        case SwFieldIds::DbNextSet: // Moving to next mail merge record
+        case SwFieldIds::DbNumSet: // Moving to a specific mail merge record
+        case SwFieldIds::DbSetNumber: // Number of current mail merge record
+            return true;
+        default:
+            return false;
+    }
+}
+
 bool SwDoc::ConvertFieldsToText(SwRootFrame const& rLayout)
 {
     bool bRet = false;
     getIDocumentFieldsAccess().LockExpFields();
     GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_REPLACE, nullptr );
 
+    const bool bOnlyConvertDBFields
+        = 
officecfg::Office::Writer::FormLetter::ConvertToTextOnlyMMFields::get();
+
     const SwFieldTypes* pMyFieldTypes = 
getIDocumentFieldsAccess().GetFieldTypes();
     const SwFieldTypes::size_type nCount = pMyFieldTypes->size();
     //go backward, field types are removed
@@ -1624,6 +1646,9 @@ bool SwDoc::ConvertFieldsToText(SwRootFrame const& 
rLayout)
         if ( SwFieldIds::Postit == pCurType->Which() )
             continue;
 
+        if (bOnlyConvertDBFields && !IsMailMergeField(pCurType->Which()))
+            continue;
+
         std::vector<SwFormatField*> vFieldFormats;
         pCurType->GatherFields(vFieldFormats, false);
         for(const auto& rpFieldFormat : vFieldFormats)
@@ -1634,67 +1659,66 @@ bool SwDoc::ConvertFieldsToText(SwRootFrame const& 
rLayout)
 
             bool bSkip = !pTextField ||
                          !pTextField->GetpTextNode()->GetNodes().IsDocNodes();
+            if (bSkip)
+                continue;
 
-            if (!bSkip)
+            bool bInHeaderFooter = 
IsInHeaderFooter(*pTextField->GetpTextNode());
+            const SwFormatField& rFormatField = pTextField->GetFormatField();
+            const SwField*  pField = rFormatField.GetField();
+
+            //#i55595# some fields have to be excluded in headers/footers
+            SwFieldIds nWhich = pField->GetTyp()->Which();
+            if(!bInHeaderFooter ||
+                    (nWhich != SwFieldIds::PageNumber &&
+                    nWhich != SwFieldIds::Chapter &&
+                    nWhich != SwFieldIds::GetExp&&
+                    nWhich != SwFieldIds::SetExp&&
+                    nWhich != SwFieldIds::Input&&
+                    nWhich != SwFieldIds::RefPageGet&&
+                    nWhich != SwFieldIds::RefPageSet))
             {
-                bool bInHeaderFooter = 
IsInHeaderFooter(*pTextField->GetpTextNode());
-                const SwFormatField& rFormatField = 
pTextField->GetFormatField();
-                const SwField*  pField = rFormatField.GetField();
-
-                //#i55595# some fields have to be excluded in headers/footers
-                SwFieldIds nWhich = pField->GetTyp()->Which();
-                if(!bInHeaderFooter ||
-                        (nWhich != SwFieldIds::PageNumber &&
-                        nWhich != SwFieldIds::Chapter &&
-                        nWhich != SwFieldIds::GetExp&&
-                        nWhich != SwFieldIds::SetExp&&
-                        nWhich != SwFieldIds::Input&&
-                        nWhich != SwFieldIds::RefPageGet&&
-                        nWhich != SwFieldIds::RefPageSet))
-                {
-                    OUString sText = pField->ExpandField(true, &rLayout);
+                OUString sText = pField->ExpandField(true, &rLayout);
 
-                    // database fields should not convert their command into 
text
-                    if( SwFieldIds::Database == pCurType->Which() && 
!static_cast<const SwDBField*>(pField)->IsInitialized())
-                        sText.clear();
+                // database fields should not convert their command into text
+                if( SwFieldIds::Database == pCurType->Which() && 
!static_cast<const SwDBField*>(pField)->IsInitialized())
+                    sText.clear();
 
-                    SwPaM aInsertPam(*pTextField->GetpTextNode(), 
pTextField->GetStart());
-                    aInsertPam.SetMark();
+                SwPaM aInsertPam(*pTextField->GetpTextNode(), 
pTextField->GetStart());
+                aInsertPam.SetMark();
 
-                    // go to the end of the field
-                    const SwTextField *pFieldAtEnd = 
sw::DocumentFieldsManager::GetTextFieldAtPos(*aInsertPam.End());
-                    if (pFieldAtEnd && pFieldAtEnd->Which() == 
RES_TXTATR_INPUTFIELD)
-                    {
-                        SwPosition &rEndPos = *aInsertPam.GetPoint();
-                        rEndPos.SetContent( 
SwCursorShell::EndOfInputFieldAtPos( *aInsertPam.End() ) );
-                    }
-                    else
-                    {
-                        aInsertPam.Move();
-                    }
-
-                    // first insert the text after field to keep the field's 
attributes,
-                    // then delete the field
-                    if (!sText.isEmpty())
-                    {
-                        // to keep the position after insert
-                        SwPaM aDelPam( *aInsertPam.GetMark(), 
*aInsertPam.GetPoint() );
-                        aDelPam.Move( fnMoveBackward );
-                        aInsertPam.DeleteMark();
+                // go to the end of the field
+                const SwTextField *pFieldAtEnd = 
sw::DocumentFieldsManager::GetTextFieldAtPos(*aInsertPam.End());
+                if (pFieldAtEnd && pFieldAtEnd->Which() == 
RES_TXTATR_INPUTFIELD)
+                {
+                    SwPosition &rEndPos = *aInsertPam.GetPoint();
+                    rEndPos.SetContent( SwCursorShell::EndOfInputFieldAtPos( 
*aInsertPam.End() ) );
+                }
+                else
+                {
+                    aInsertPam.Move();
+                }
 
-                        getIDocumentContentOperations().InsertString( 
aInsertPam, sText );
+                // first insert the text after field to keep the field's 
attributes,
+                // then delete the field
+                if (!sText.isEmpty())
+                {
+                    // to keep the position after insert
+                    SwPaM aDelPam( *aInsertPam.GetMark(), 
*aInsertPam.GetPoint() );
+                    aDelPam.Move( fnMoveBackward );
+                    aInsertPam.DeleteMark();
 
-                        aDelPam.Move();
-                        // finally remove the field
-                        getIDocumentContentOperations().DeleteAndJoin( aDelPam 
);
-                    }
-                    else
-                    {
-                        getIDocumentContentOperations().DeleteAndJoin( 
aInsertPam );
-                    }
+                    getIDocumentContentOperations().InsertString( aInsertPam, 
sText );
 
-                    bRet = true;
+                    aDelPam.Move();
+                    // finally remove the field
+                    getIDocumentContentOperations().DeleteAndJoin( aDelPam );
                 }
+                else
+                {
+                    getIDocumentContentOperations().DeleteAndJoin( aInsertPam 
);
+                }
+
+                bRet = true;
             }
         }
     }

Reply via email to