summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/CppunitTest_sw_mailmerge.mk4
-rw-r--r--sw/inc/IDocumentSettingAccess.hxx1
-rw-r--r--sw/inc/doc.hxx3
-rw-r--r--sw/inc/ndhints.hxx26
-rw-r--r--sw/inc/ndtxt.hxx12
-rw-r--r--sw/inc/viewsh.hxx2
-rw-r--r--sw/qa/extras/mailmerge/data/5-with-blanks.odsbin0 -> 9193 bytes
-rw-r--r--sw/qa/extras/mailmerge/data/tdf35798-legacy.fodt37
-rw-r--r--sw/qa/extras/mailmerge/data/tdf35798-legacy.odtbin0 -> 9557 bytes
-rw-r--r--sw/qa/extras/mailmerge/data/tdf35798-new.fodt38
-rw-r--r--sw/qa/extras/mailmerge/data/tdf35798-new.odtbin0 -> 9556 bytes
-rw-r--r--sw/qa/extras/mailmerge/mailmerge.cxx141
-rw-r--r--sw/source/core/doc/DocumentSettingManager.cxx7
-rw-r--r--sw/source/core/doc/doc.cxx128
-rw-r--r--sw/source/core/doc/doctxm.cxx4
-rw-r--r--sw/source/core/inc/DocumentSettingManager.hxx1
-rw-r--r--sw/source/core/text/txtfrm.cxx9
-rw-r--r--sw/source/core/txtnode/atrfld.cxx27
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx2
-rw-r--r--sw/source/core/txtnode/thints.cxx71
-rw-r--r--sw/source/core/view/viewsh.cxx20
-rw-r--r--sw/source/filter/xml/xmlimp.cxx26
-rw-r--r--sw/source/ui/config/optcomp.cxx33
-rw-r--r--sw/source/uibase/app/docshini.cxx22
-rw-r--r--sw/source/uibase/uno/SwXDocumentSettings.cxx18
-rw-r--r--sw/uiconfig/swriter/ui/optcompatpage.ui1
26 files changed, 503 insertions, 130 deletions
diff --git a/sw/CppunitTest_sw_mailmerge.mk b/sw/CppunitTest_sw_mailmerge.mk
index 7826c312ddb2..6cdd53262b40 100644
--- a/sw/CppunitTest_sw_mailmerge.mk
+++ b/sw/CppunitTest_sw_mailmerge.mk
@@ -45,7 +45,10 @@ $(eval $(call gb_CppunitTest_use_components,sw_mailmerge, \
dbaccess/util/dba \
embeddedobj/util/embobj \
filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
filter/source/storagefilterdetect/storagefd \
+ filter/source/xmlfilteradaptor/xmlfa \
+ filter/source/xmlfilterdetect/xmlfd \
forms/util/frm \
framework/util/fwk \
i18npool/util/i18npool \
@@ -78,6 +81,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_mailmerge, \
) \
) \
xmloff/util/xo \
+ xmlscript/util/xmlscript \
))
$(eval $(call gb_CppunitTest_use_instdir_configuration,sw_mailmerge))
diff --git a/sw/inc/IDocumentSettingAccess.hxx b/sw/inc/IDocumentSettingAccess.hxx
index f152fef3ff26..7dbfdf5331dd 100644
--- a/sw/inc/IDocumentSettingAccess.hxx
+++ b/sw/inc/IDocumentSettingAccess.hxx
@@ -82,6 +82,7 @@ enum class DocumentSettingId
SURROUND_TEXT_WRAP_SMALL,
PROP_LINE_SPACING_SHRINKS_FIRST_LINE,
SUBTRACT_FLYS,
+ EMPTY_DB_FIELD_HIDES_PARA,
// COMPATIBILITY FLAGS END
BROWSE_MODE,
HTML_MODE,
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 90ec57051f12..cdd82b1306b1 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -505,6 +505,9 @@ public:
::sw::DocumentFieldsManager & GetDocumentFieldsManager();
+ bool FieldCanHidePara(sal_uInt16 eFieldId) const;
+ bool FieldHidesPara(const SwField& rField) const;
+
// IDocumentContentOperations
IDocumentContentOperations const & getIDocumentContentOperations() const;
IDocumentContentOperations & getIDocumentContentOperations();
diff --git a/sw/inc/ndhints.hxx b/sw/inc/ndhints.hxx
index 6643a6a920c3..88f61a8700d7 100644
--- a/sw/inc/ndhints.hxx
+++ b/sw/inc/ndhints.hxx
@@ -77,6 +77,8 @@ class SwpHtEnd : public o3tl::sorted_vector<SwTextAttr*, CompareSwpHtEnd,
class SwpHints
{
private:
+ const SwTextNode& m_rParent;
+
// SAL_MAX_SIZE is used by GetStartOf to return
// failure, so just allow SAL_MAX_SIZE-1 hints
static const size_t MAX_HINTS = SAL_MAX_SIZE-1;
@@ -88,9 +90,11 @@ private:
/// true: the Node is in Split and Frames are moved
bool m_bInSplitNode : 1;
- /// m_bHasHiddenParaField is invalid, call CalcHiddenParaField()
- bool m_bCalcHiddenParaField : 1;
- bool m_bHasHiddenParaField : 1; ///< HiddenParaField
+ // m_bHiddenByParaField is invalid, call CalcHiddenParaField()
+ mutable bool m_bCalcHiddenParaField : 1;
+ // if all fields controlling visibility of the paragraph require to hide it
+ // (if there's no such fields, or if any field requires to show, then this is false)
+ mutable bool m_bHiddenByParaField : 1;
bool m_bFootnote : 1; ///< footnotes
bool m_bDDEFields : 1; ///< the TextNode has DDE fields
@@ -108,15 +112,15 @@ private:
void Delete( SwTextAttr* pTextHt );
void SetInSplitNode(bool bInSplit) { m_bInSplitNode = bInSplit; }
- void SetCalcHiddenParaField() { m_bCalcHiddenParaField = true; }
- void SetHiddenParaField( const bool bNew ) { m_bHasHiddenParaField = bNew; }
- bool HasHiddenParaField() const
+ void SetCalcHiddenParaField() const { m_bCalcHiddenParaField = true; }
+ void SetHiddenByParaField( const bool bNew ) const { m_bHiddenByParaField = bNew; }
+ bool IsHiddenByParaField() const
{
if ( m_bCalcHiddenParaField )
{
- (const_cast<SwpHints*>(this))->CalcHiddenParaField();
+ CalcHiddenParaField();
}
- return m_bHasHiddenParaField;
+ return m_bHiddenByParaField;
}
void InsertNesting(SwTextAttrNesting & rNewHint);
@@ -144,7 +148,7 @@ private:
#endif
public:
- SwpHints();
+ SwpHints(const SwTextNode& rParent);
size_t Count() const { return m_HintsByStart.size(); }
bool Contains( const SwTextAttr *pHt ) const;
@@ -179,8 +183,8 @@ public:
bool HasFootnote() const { return m_bFootnote; }
bool IsInSplitNode() const { return m_bInSplitNode; }
- /// calc current value of m_bHasHiddenParaField, returns true iff changed
- bool CalcHiddenParaField();
+ // calc current value of m_bHiddenByParaField, returns true iff changed
+ bool CalcHiddenParaField() const; // changes mutable state
DECL_FIXEDMEMPOOL_NEWDEL(SwpHints)
};
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 87f4a7b28e81..73d44de8915e 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -21,6 +21,7 @@
#include <cppuhelper/weakref.hxx>
+#include "doc.hxx"
#include "swdllapi.h"
#include <node.hxx>
#include <hintids.hxx>
@@ -702,8 +703,13 @@ public:
{ if (m_pSwpHints) m_pSwpHints->SetCalcHiddenParaField(); }
/// is the paragraph visible?
- inline bool HasHiddenParaField() const
- { return m_pSwpHints && m_pSwpHints->HasHiddenParaField(); }
+ inline bool IsHiddenByParaField() const
+ { return m_pSwpHints && m_pSwpHints->IsHiddenByParaField(); }
+
+ bool FieldCanHidePara(sal_uInt16 eFieldId) const
+ { return GetDoc()->FieldCanHidePara(eFieldId); }
+ bool FieldHidesPara(const SwField& rField) const
+ { return GetDoc()->FieldHidesPara(rField); }
/// Hidden Paragraph Field:
@@ -812,7 +818,7 @@ inline SwpHints& SwTextNode::GetOrCreateSwpHints()
{
if ( !m_pSwpHints )
{
- m_pSwpHints = new SwpHints;
+ m_pSwpHints = new SwpHints(*this);
}
return *m_pSwpHints;
}
diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx
index 94d458753d7b..5b964fdcdbcb 100644
--- a/sw/inc/viewsh.hxx
+++ b/sw/inc/viewsh.hxx
@@ -420,6 +420,8 @@ public:
void SetSubtractFlysAnchoredAtFlys(bool bSubtractFlysAnchoredAtFlys);
+ void SetEmptyDbFieldHidesPara(bool bEmptyDbFieldHidesPara);
+
// DOCUMENT COMPATIBILITY FLAGS END
// Calls Idle-formatter of Layout.
diff --git a/sw/qa/extras/mailmerge/data/5-with-blanks.ods b/sw/qa/extras/mailmerge/data/5-with-blanks.ods
new file mode 100644
index 000000000000..722f74830688
--- /dev/null
+++ b/sw/qa/extras/mailmerge/data/5-with-blanks.ods
Binary files differ
diff --git a/sw/qa/extras/mailmerge/data/tdf35798-legacy.fodt b/sw/qa/extras/mailmerge/data/tdf35798-legacy.fodt
new file mode 100644
index 000000000000..c6dd8661e869
--- /dev/null
+++ b/sw/qa/extras/mailmerge/data/tdf35798-legacy.fodt
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2014-10-22T13:27:38.673154279</meta:creation-date><dc:date>2018-05-19T13:45:25.911000000</dc:date><meta:editing-duration>PT6M54S</meta:editing-duration><meta:editing-cycles>4</meta:editing-cycles><meta:generator>LibreOfficeDev/6.1.0.0.alpha1$Windows_X86_64 LibreOffice_project/dd1ab570d5791145c10a4e8f28b048ec8f70edb0</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="8" meta:word-count="37" meta:character-count="228"/></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="CurrentDatabaseDataSource" config:type="string">5-with-blanks</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommand" config:type="string">names</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:automatic-styles>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p>Heading</text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display></text:p>
+ <text:p>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display></text:p>
+ <text:p>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display><text:s/>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display></text:p>
+ <text:p>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display><text:s/>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display><text:s/>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display><text:s/>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Trailing text</text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/mailmerge/data/tdf35798-legacy.odt b/sw/qa/extras/mailmerge/data/tdf35798-legacy.odt
new file mode 100644
index 000000000000..fe37e5e962fd
--- /dev/null
+++ b/sw/qa/extras/mailmerge/data/tdf35798-legacy.odt
Binary files differ
diff --git a/sw/qa/extras/mailmerge/data/tdf35798-new.fodt b/sw/qa/extras/mailmerge/data/tdf35798-new.fodt
new file mode 100644
index 000000000000..8de149cab75a
--- /dev/null
+++ b/sw/qa/extras/mailmerge/data/tdf35798-new.fodt
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2014-10-22T13:27:38.673154279</meta:creation-date><dc:date>2018-05-19T13:45:25.911000000</dc:date><meta:editing-duration>PT6M54S</meta:editing-duration><meta:editing-cycles>4</meta:editing-cycles><meta:generator>LibreOfficeDev/6.1.0.0.alpha1$Windows_X86_64 LibreOffice_project/dd1ab570d5791145c10a4e8f28b048ec8f70edb0</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="8" meta:word-count="37" meta:character-count="228"/></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="CurrentDatabaseDataSource" config:type="string">5-with-blanks</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommand" config:type="string">names</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
+ <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">true</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:automatic-styles>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:p>Heading</text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display></text:p>
+ <text:p>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display></text:p>
+ <text:p>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display><text:s/>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display></text:p>
+ <text:p>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display><text:s/>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Title: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Title" text:database-name="5-with-blanks">&lt;Title&gt;</text:database-display><text:s/>First Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="First Name" text:database-name="5-with-blanks">&lt;First Name&gt;</text:database-display><text:s/>Last Name: <text:database-display text:table-name="names" text:table-type="table" text:column-name="Last Name" text:database-name="5-with-blanks">&lt;Last Name&gt;</text:database-display></text:p>
+ <text:p>Trailing text</text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/mailmerge/data/tdf35798-new.odt b/sw/qa/extras/mailmerge/data/tdf35798-new.odt
new file mode 100644
index 000000000000..84323b96e658
--- /dev/null
+++ b/sw/qa/extras/mailmerge/data/tdf35798-new.odt
Binary files differ
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx
index 838c7ab0007b..6203da94c616 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -671,5 +671,146 @@ DECLARE_FILE_MAILMERGE_TEST(testTdf102010, "empty.odt", "10-testing-addresses.od
loadMailMergeDocument( 1 );
}
+namespace
+{
+constexpr char const* const EmptyValuesLegacyData[][8]
+ = { { "Heading", "Title: ", "First Name: firstname1", "Last Name: lastname1",
+ "Title: First Name: firstname1", "First Name: firstname1 Last Name: lastname1",
+ "Title: First Name: firstname1 Last Name: lastname1", "Trailing text" },
+ { "Heading", "Title: title2", "First Name: ", "Last Name: lastname2",
+ "Title: title2 First Name: ", "First Name: Last Name: lastname2",
+ "Title: title2 First Name: Last Name: lastname2", "Trailing text" },
+ { "Heading", "Title: title3", "First Name: firstname3", "Last Name: ",
+ "Title: title3 First Name: firstname3", "First Name: firstname3 Last Name: ",
+ "Title: title3 First Name: firstname3 Last Name: ", "Trailing text" },
+ { "Heading", "Title: ", "First Name: ", "Last Name: lastname4",
+ "Title: First Name: ", "First Name: Last Name: lastname4",
+ "Title: First Name: Last Name: lastname4", "Trailing text" },
+ { "Heading", "Title: title5", "First Name: ", "Last Name: ", "Title: title5 First Name: ",
+ "First Name: Last Name: ", "Title: title5 First Name: Last Name: ", "Trailing text" } };
+constexpr char const* const EmptyValuesNewData[][8]
+ = { { "Heading", "First Name: firstname1", "Last Name: lastname1",
+ "Title: First Name: firstname1", "First Name: firstname1 Last Name: lastname1",
+ "Title: First Name: firstname1 Last Name: lastname1", "Trailing text" },
+ { "Heading", "Title: title2", "Last Name: lastname2",
+ "Title: title2 First Name: ", "First Name: Last Name: lastname2",
+ "Title: title2 First Name: Last Name: lastname2", "Trailing text" },
+ { "Heading", "Title: title3", "First Name: firstname3",
+ "Title: title3 First Name: firstname3", "First Name: firstname3 Last Name: ",
+ "Title: title3 First Name: firstname3 Last Name: ", "Trailing text" },
+ { "Heading", "Last Name: lastname4", "First Name: Last Name: lastname4",
+ "Title: First Name: Last Name: lastname4", "Trailing text" },
+ { "Heading", "Title: title5", "Title: title5 First Name: ",
+ "Title: title5 First Name: Last Name: ", "Trailing text" } };
+}
+
+// The following four tests (testEmptyValuesLegacyODT, testEmptyValuesNewODT, (testEmptyValuesLegacyFODT, testEmptyValuesNewFODT)
+// check that for native documents without "EmptyDbFieldHidesPara" compatibility option, all paragraphs are exported visible,
+// while for documents with the option enabled, the paragraphs with all Database fields having empty values are hidden.
+
+DECLARE_FILE_MAILMERGE_TEST(testEmptyValuesLegacyODT, "tdf35798-legacy.odt", "5-with-blanks.ods",
+ "names")
+{
+ executeMailMerge();
+ for (int doc = 0; doc < 5; ++doc)
+ {
+ loadMailMergeDocument(doc);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ pDoc->RemoveInvisibleContent();
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+ for (int i = 0; i < 8; ++i)
+ {
+ auto xPara = getParagraph(i+1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in doc " + OString::number(doc) + " paragraph " + OString::number(i + 1))
+ .getStr(),
+ OUString::createFromAscii(EmptyValuesLegacyData[doc][i]), xPara->getString());
+ }
+ CPPUNIT_ASSERT_EQUAL(8, getParagraphs());
+ }
+}
+
+DECLARE_FILE_MAILMERGE_TEST(testEmptyValuesNewODT, "tdf35798-new.odt", "5-with-blanks.ods",
+ "names")
+{
+ executeMailMerge();
+ for (int doc = 0; doc < 5; ++doc)
+ {
+ loadMailMergeDocument(doc);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ pDoc->RemoveInvisibleContent();
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+ int i;
+ for (i = 0; i < 8; ++i)
+ {
+ const char* pExpected = EmptyValuesNewData[doc][i];
+ if (!pExpected)
+ break;
+ auto xPara = getParagraph(i + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in doc " + OString::number(doc) + " paragraph " + OString::number(i + 1))
+ .getStr(),
+ OUString::createFromAscii(pExpected), xPara->getString());
+ }
+ CPPUNIT_ASSERT_EQUAL(i, getParagraphs());
+ }
+}
+
+DECLARE_FILE_MAILMERGE_TEST(testEmptyValuesLegacyFODT, "tdf35798-legacy.fodt", "5-with-blanks.ods",
+ "names")
+{
+ executeMailMerge();
+ for (int doc = 0; doc < 5; ++doc)
+ {
+ loadMailMergeDocument(doc);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ pDoc->RemoveInvisibleContent();
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+ for (int i = 0; i < 8; ++i)
+ {
+ auto xPara = getParagraph(i + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in doc " + OString::number(doc) + " paragraph " + OString::number(i + 1))
+ .getStr(),
+ OUString::createFromAscii(EmptyValuesLegacyData[doc][i]), xPara->getString());
+ }
+ CPPUNIT_ASSERT_EQUAL(8, getParagraphs());
+ }
+}
+
+DECLARE_FILE_MAILMERGE_TEST(testEmptyValuesNewFODT, "tdf35798-new.fodt", "5-with-blanks.ods",
+ "names")
+{
+ executeMailMerge();
+ for (int doc = 0; doc < 5; ++doc)
+ {
+ loadMailMergeDocument(doc);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ pDoc->RemoveInvisibleContent();
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+ int i;
+ for (i = 0; i < 8; ++i)
+ {
+ const char* pExpected = EmptyValuesNewData[doc][i];
+ if (!pExpected)
+ break;
+ auto xPara = getParagraph(i + 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString("in doc " + OString::number(doc) + " paragraph " + OString::number(i + 1))
+ .getStr(),
+ OUString::createFromAscii(pExpected), xPara->getString());
+ }
+ CPPUNIT_ASSERT_EQUAL(i, getParagraphs());
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentSettingManager.cxx b/sw/source/core/doc/DocumentSettingManager.cxx
index 69361f0add48..198504d0dd13 100644
--- a/sw/source/core/doc/DocumentSettingManager.cxx
+++ b/sw/source/core/doc/DocumentSettingManager.cxx
@@ -112,6 +112,7 @@ sw::DocumentSettingManager::DocumentSettingManager(SwDoc &rDoc)
mbConsiderWrapOnObjPos = aOptions.IsConsiderWrappingStyle();
mbDoNotJustifyLinesWithManualBreak = !aOptions.IsExpandWordSpace();
+ mbEmptyDbFieldHidesPara = aOptions.IsEmptyDbFieldHidesPara();
}
else
{
@@ -126,6 +127,7 @@ sw::DocumentSettingManager::DocumentSettingManager(SwDoc &rDoc)
mbUseFormerTextWrapping = false;
mbConsiderWrapOnObjPos = false;
mbDoNotJustifyLinesWithManualBreak = true;
+ mbEmptyDbFieldHidesPara = true;
}
// COMPATIBILITY FLAGS END
@@ -200,6 +202,7 @@ bool sw::DocumentSettingManager::get(/*[in]*/ DocumentSettingId id) const
case DocumentSettingId::EMBED_FONTS: return mEmbedFonts;
case DocumentSettingId::EMBED_SYSTEM_FONTS: return mEmbedSystemFonts;
case DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING: return mApplyParagraphMarkFormatToNumbering;
+ case DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA: return mbEmptyDbFieldHidesPara;
default:
OSL_FAIL("Invalid setting id");
}
@@ -421,6 +424,9 @@ void sw::DocumentSettingManager::set(/*[in]*/ DocumentSettingId id, /*[in]*/ boo
case DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING:
mApplyParagraphMarkFormatToNumbering = value;
break;
+ case DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA:
+ mbEmptyDbFieldHidesPara = value;
+ break;
default:
OSL_FAIL("Invalid setting id");
}
@@ -567,6 +573,7 @@ void sw::DocumentSettingManager::ReplaceCompatibilityOptions(const DocumentSetti
mbTabRelativeToIndent = rSource.mbTabRelativeToIndent;
mbTabAtLeftIndentForParagraphsInList = rSource.mbTabAtLeftIndentForParagraphsInList;
mbMsWordCompTrailingBlanks = rSource.mbMsWordCompTrailingBlanks;
+ mbEmptyDbFieldHidesPara = rSource.mbEmptyDbFieldHidesPara;
}
sal_uInt32 sw::DocumentSettingManager::Getn32DummyCompatibilityOptions1() const
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 36b77722035f..c28d1be8643e 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -1316,6 +1316,73 @@ void SwDoc::Summary( SwDoc* pExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, bool bIm
}
}
+namespace
+{
+void RemoveOrDeleteContents(SwTextNode* pTextNd, IDocumentContentOperations& xOperations)
+{
+ SwPaM aPam(*pTextNd, 0, *pTextNd, pTextNd->GetText().getLength());
+
+ // Remove hidden paragraph or delete contents:
+ // Delete contents if
+ // 1. removing the paragraph would result in an empty section or
+ // 2. if the paragraph is the last paragraph in the section and
+ // there is no paragraph in front of the paragraph:
+ if ((2 == pTextNd->EndOfSectionIndex() - pTextNd->StartOfSectionIndex())
+ || (1 == pTextNd->EndOfSectionIndex() - pTextNd->GetIndex()
+ && !pTextNd->GetNodes()[pTextNd->GetIndex() - 1]->GetTextNode()))
+ {
+ xOperations.DeleteRange(aPam);
+ }
+ else
+ {
+ aPam.DeleteMark();
+ xOperations.DelFullPara(aPam);
+ }
+}
+// Returns if the data was actually modified
+bool HandleHidingField(SwFormatField& rFormatField, const SwNodes& rNodes,
+ IDocumentContentOperations& xOperations)
+{
+ SwTextNode* pTextNd;
+ if (rFormatField.GetTextField()
+ && nullptr != (pTextNd = rFormatField.GetTextField()->GetpTextNode())
+ && pTextNd->GetpSwpHints() && pTextNd->IsHiddenByParaField()
+ && &pTextNd->GetNodes() == &rNodes)
+ {
+ RemoveOrDeleteContents(pTextNd, xOperations);
+ return true;
+ }
+ return false;
+}
+}
+
+bool SwDoc::FieldCanHidePara(sal_uInt16 eFieldId) const
+{
+ switch (eFieldId)
+ {
+ case RES_HIDDENPARAFLD:
+ return true;
+ case RES_DBFLD:
+ return GetDocumentSettingManager().get(
+ DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA);
+ default:
+ return false;
+ }
+}
+
+bool SwDoc::FieldHidesPara(const SwField& rField) const
+{
+ switch (rField.GetTyp()->Which())
+ {
+ case RES_HIDDENPARAFLD:
+ return static_cast<const SwHiddenParaField&>(rField).IsHidden();
+ case RES_DBFLD:
+ return FieldCanHidePara(RES_DBFLD) && rField.ExpandField(true).isEmpty();
+ default:
+ return false;
+ }
+}
+
/// Remove the invisible content from the document e.g. hidden areas, hidden paragraphs
bool SwDoc::RemoveInvisibleContent()
{
@@ -1323,35 +1390,22 @@ bool SwDoc::RemoveInvisibleContent()
GetIDocumentUndoRedo().StartUndo( UNDO_UI_DELETE_INVISIBLECNTNT, nullptr );
{
- SwTextNode* pTextNd;
- SwIterator<SwFormatField,SwFieldType> aIter( *getIDocumentFieldsAccess().GetSysFieldType( RES_HIDDENPARAFLD ) );
- for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
+ // Removing some nodes for one SwFieldIds::Database type might remove the type from
+ // document's field types, invalidating iterators. So, we need to create own list of
+ // matching types prior to processing them.
+ std::vector<const SwFieldType*> aHidingFieldTypes;
+ for (const auto* pType : *getIDocumentFieldsAccess().GetFieldTypes())
{
- if( pFormatField->GetTextField() &&
- nullptr != ( pTextNd = pFormatField->GetTextField()->GetpTextNode() ) &&
- pTextNd->GetpSwpHints() && pTextNd->HasHiddenParaField() &&
- &pTextNd->GetNodes() == &GetNodes() )
- {
- bRet = true;
- SwPaM aPam(*pTextNd, 0, *pTextNd, pTextNd->GetText().getLength());
-
- // Remove hidden paragraph or delete contents:
- // Delete contents if
- // 1. removing the paragraph would result in an empty section or
- // 2. if the paragraph is the last paragraph in the section and
- // there is no paragraph in front of the paragraph:
- if ( ( 2 == pTextNd->EndOfSectionIndex() - pTextNd->StartOfSectionIndex() ) ||
- ( 1 == pTextNd->EndOfSectionIndex() - pTextNd->GetIndex() &&
- !GetNodes()[ pTextNd->GetIndex() - 1 ]->GetTextNode() ) )
- {
- getIDocumentContentOperations().DeleteRange( aPam );
- }
- else
- {
- aPam.DeleteMark();
- getIDocumentContentOperations().DelFullPara( aPam );
- }
- }
+ if (FieldCanHidePara(pType->Which()))
+ aHidingFieldTypes.push_back(pType);
+ }
+ for (const auto* pType : aHidingFieldTypes)
+ {
+ SwIterator<SwFormatField, SwFieldType> aIter(*pType);
+ for (SwFormatField* pFormatField = aIter.First(); pFormatField;
+ pFormatField = aIter.Next())
+ bRet |= HandleHidingField(*pFormatField, GetNodes(),
+ getIDocumentContentOperations());
}
}
@@ -1367,23 +1421,7 @@ bool SwDoc::RemoveInvisibleContent()
{
bRemoved = true;
bRet = true;
-
- // Remove hidden paragraph or delete contents:
- // Delete contents if
- // 1. removing the paragraph would result in an empty section or
- // 2. if the paragraph is the last paragraph in the section and
- // there is no paragraph in front of the paragraph:
- if ( ( 2 == pTextNd->EndOfSectionIndex() - pTextNd->StartOfSectionIndex() ) ||
- ( 1 == pTextNd->EndOfSectionIndex() - pTextNd->GetIndex() &&
- !GetNodes()[ pTextNd->GetIndex() - 1 ]->GetTextNode() ) )
- {
- getIDocumentContentOperations().DeleteRange( aPam );
- }
- else
- {
- aPam.DeleteMark();
- getIDocumentContentOperations().DelFullPara( aPam );
- }
+ RemoveOrDeleteContents(pTextNd, getIDocumentContentOperations());
}
else if ( pTextNd->HasHiddenCharAttribute( false ) )
{
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index 46496a78d662..08c8249ec40e 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -1149,7 +1149,7 @@ void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
pTOXSrc->GetText().getLength() && pTOXSrc->HasWriterListeners() &&
pTOXSrc->getLayoutFrame( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) &&
(!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc ) == pOwnChapterNode ) &&
- !pTOXSrc->HasHiddenParaField() &&
+ !pTOXSrc->IsHiddenByParaField() &&
!SwScriptInfo::IsInHiddenRange( *pTOXSrc, pTextMark->GetStart() ) )
{
SwTOXSortTabBase* pBase = nullptr;
@@ -1206,7 +1206,7 @@ void SwTOXBaseSection::UpdateOutline( const SwTextNode* pOwnChapterNode )
if( pTextNd && pTextNd->Len() && pTextNd->HasWriterListeners() &&
sal_uInt16( pTextNd->GetAttrOutlineLevel()) <= GetLevel() &&
pTextNd->getLayoutFrame( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) &&
- !pTextNd->HasHiddenParaField() &&
+ !pTextNd->IsHiddenByParaField() &&
!pTextNd->HasHiddenCharAttribute( true ) &&
( !IsFromChapter() ||
::lcl_FindChapterNode( *pTextNd ) == pOwnChapterNode ))
diff --git a/sw/source/core/inc/DocumentSettingManager.hxx b/sw/source/core/inc/DocumentSettingManager.hxx
index 6efbb35ee59d..6ee2e425404f 100644
--- a/sw/source/core/inc/DocumentSettingManager.hxx
+++ b/sw/source/core/inc/DocumentSettingManager.hxx
@@ -156,6 +156,7 @@ class DocumentSettingManager :
bool mApplyParagraphMarkFormatToNumbering;
bool mbLastBrowseMode : 1;
+ bool mbEmptyDbFieldHidesPara;
public:
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 217f449e5055..53db798d265e 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -439,12 +439,11 @@ bool SwTextFrame::IsHiddenNow() const
return true;
}
- const bool bHiddenCharsHidePara = GetTextNode()->HasHiddenCharAttribute( true );
- const bool bHiddenParaField = GetTextNode()->HasHiddenParaField();
- const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
-
- if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
+ if ( const SwViewShell* pVsh = getRootFrame()->GetCurrShell() )
{
+ const bool bHiddenCharsHidePara = GetTextNode()->HasHiddenCharAttribute(true);
+ const bool bHiddenParaField = GetTextNode()->IsHiddenByParaField();
+
if (
( bHiddenParaField &&
( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
diff --git a/sw/source/core/txtnode/atrfld.cxx b/sw/source/core/txtnode/atrfld.cxx
index ed8f0dbf5024..0c76827d6159 100644
--- a/sw/source/core/txtnode/atrfld.cxx
+++ b/sw/source/core/txtnode/atrfld.cxx
@@ -381,19 +381,26 @@ void SwTextField::ExpandTextField(const bool bForceNotify) const
const SwField* pField = GetFormatField().GetField();
const OUString aNewExpand( pField->ExpandField(m_pTextNode->GetDoc()->IsClipBoard()) );
+ const sal_uInt16 nWhich = pField->GetTyp()->Which();
+ const bool bSameExpandSimpleNotification
+ = RES_CHAPTERFLD != nWhich && RES_PAGENUMBERFLD != nWhich
+ && RES_REFPAGEGETFLD != nWhich
+ // Page count fields to not use aExpand during formatting,
+ // therefore an invalidation of the text frame has to be triggered even if aNewExpand == aExpand:
+ && (RES_DOCSTATFLD != nWhich
+ || DS_PAGE != static_cast<const SwDocStatField*>(pField)->GetSubType())
+ && (RES_GETEXPFLD != nWhich
+ || static_cast<const SwGetExpField*>(pField)->IsInBodyText());
+
+ bool bHiddenParaChanged = false;
+ if (aNewExpand != m_aExpand || bSameExpandSimpleNotification)
+ bHiddenParaChanged = m_pTextNode->CalcHiddenParaField();
+
if (aNewExpand == m_aExpand)
{
- // Bei Seitennummernfeldern
- const sal_uInt16 nWhich = pField->GetTyp()->Which();
- if ( RES_CHAPTERFLD != nWhich
- && RES_PAGENUMBERFLD != nWhich
- && RES_REFPAGEGETFLD != nWhich
- // Page count fields to not use aExpand during formatting,
- // therefore an invalidation of the text frame has to be triggered even if aNewExpand == aExpand:
- && ( RES_DOCSTATFLD != nWhich || DS_PAGE != static_cast<const SwDocStatField*>(pField)->GetSubType() )
- && ( RES_GETEXPFLD != nWhich || static_cast<const SwGetExpField*>(pField)->IsInBodyText() ) )
+ if ( bSameExpandSimpleNotification )
{
- if( m_pTextNode->CalcHiddenParaField() )
+ if( bHiddenParaChanged )
{
m_pTextNode->ModifyNotification( nullptr, nullptr );
}
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index d5947f32c856..63947574f98d 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -4201,7 +4201,7 @@ void SwTextNode::CalcHiddenCharFlags() const
// #i12836# enhanced pdf export
bool SwTextNode::IsHidden() const
{
- if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
+ if ( IsHiddenByParaField() || HasHiddenCharAttribute( true ) )
return true;
const SwSectionNode* pSectNd = FindSectionNode();
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index eb2180702b1e..a43148fc96de 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -19,6 +19,7 @@
#include <sal/config.h>
+#include <DocumentSettingManager.hxx>
#include <hintids.hxx>
#include <editeng/xmlcnitm.hxx>
#include <svl/whiter.hxx>
@@ -85,11 +86,12 @@
using namespace ::com::sun::star::i18n;
-SwpHints::SwpHints()
- : m_pHistory(nullptr)
+SwpHints::SwpHints(const SwTextNode& rParent)
+ : m_rParent(rParent)
+ , m_pHistory(nullptr)
, m_bInSplitNode(false)
, m_bCalcHiddenParaField(false)
- , m_bHasHiddenParaField(false)
+ , m_bHiddenByParaField(false)
, m_bFootnote(false)
, m_bDDEFields(false)
{
@@ -1145,21 +1147,21 @@ void SwTextNode::DestroyAttr( SwTextAttr* pAttr )
if( !pDoc->IsInDtor() )
{
SwTextField *const pTextField(static_txtattr_cast<SwTextField*>(pAttr));
- // Wenn wir ein HiddenParaField sind, dann muessen wir
- // ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
- const SwField* pField = pAttr->GetFormatField().GetField();
+ SwFieldType* pFieldType = pAttr->GetFormatField().GetField()->GetTyp();
- //JP 06-08-95: DDE-Felder bilden eine Ausnahme
- OSL_ENSURE( RES_DDEFLD == pField->GetTyp()->Which() ||
- this == pTextField->GetpTextNode(),
- "Wo steht denn dieses Feld?" );
+ //JP 06-08-95: DDE-fields are an exception
+ assert(RES_DDEFLD == pFieldType->Which() ||
+ this == pTextField->GetpTextNode());
- // bestimmte Felder mussen am Doc das Calculations-Flag updaten
- switch( pField->GetTyp()->Which() )
+ // certain fields must update the SwDoc's calculation flags
+
+ // Certain fields (like HiddenParaField) must trigger recalculation of visible flag
+ if (FieldCanHidePara(pFieldType->Which()))
+ SetCalcHiddenParaField();
+
+ switch( pFieldType->Which() )
{
case RES_HIDDENPARAFLD:
- SetCalcHiddenParaField();
- SAL_FALLTHROUGH;
case RES_DBSETNUMBERFLD:
case RES_GETEXPFLD:
case RES_DBFLD:
@@ -1172,7 +1174,7 @@ void SwTextNode::DestroyAttr( SwTextAttr* pAttr )
break;
case RES_DDEFLD:
if (GetNodes().IsDocNodes() && pTextField->GetpTextNode())
- static_cast<SwDDEFieldType*>(pField->GetTyp())->DecRefCnt();
+ static_cast<SwDDEFieldType*>(pFieldType)->DecRefCnt();
break;
case RES_POSTITFLD:
{
@@ -1462,9 +1464,8 @@ bool SwTextNode::InsertHint( SwTextAttr * const pAttr, const SetAttrMode nMode )
case RES_TXTATR_FIELD:
{
- // fuer HiddenParaFields Benachrichtigungsmechanismus
- // anwerfen
- if( RES_HIDDENPARAFLD == pAttr->GetFormatField().GetField()->GetTyp()->Which() )
+ // trigger notification for relevant fields, like HiddenParaFields
+ if (FieldCanHidePara(pAttr->GetFormatField().GetField()->GetTyp()->Which()))
{
bHiddenPara = true;
}
@@ -2599,38 +2600,32 @@ void SwpHints::CalcFlags()
}
}
-bool SwpHints::CalcHiddenParaField()
+bool SwpHints::CalcHiddenParaField() const
{
m_bCalcHiddenParaField = false;
- bool bOldHasHiddenParaField = m_bHasHiddenParaField;
- bool bNewHasHiddenParaField = false;
+ const bool bOldHiddenByParaField = m_bHiddenByParaField;
+ bool bNewHiddenByParaField = false;
const size_t nSize = Count();
- const SwTextAttr *pTextHt;
+ const SwTextAttr* pTextHt;
- for( size_t nPos = 0; nPos < nSize; ++nPos )
+ for (size_t nPos = 0; nPos < nSize; ++nPos)
{
pTextHt = Get(nPos);
const sal_uInt16 nWhich = pTextHt->Which();
- if( RES_TXTATR_FIELD == nWhich )
+ if (RES_TXTATR_FIELD == nWhich)
{
const SwFormatField& rField = pTextHt->GetFormatField();
- if( RES_HIDDENPARAFLD == rField.GetField()->GetTyp()->Which() )
+ if (m_rParent.FieldCanHidePara(rField.GetField()->GetTyp()->Which())
+ && !(bNewHiddenByParaField = m_rParent.FieldHidesPara(*rField.GetField())))
{
- if( !static_cast<const SwHiddenParaField*>(rField.GetField())->IsHidden() )
- {
- SetHiddenParaField(false);
- return bOldHasHiddenParaField != bNewHasHiddenParaField;
- }
- else
- {
- bNewHasHiddenParaField = true;
- }
+ // If there's at least one field telling not to hide, so be it
+ break;
}
}
}
- SetHiddenParaField( bNewHasHiddenParaField );
- return bOldHasHiddenParaField != bNewHasHiddenParaField;
+ SetHiddenByParaField(bNewHiddenByParaField);
+ return bOldHiddenByParaField != bNewHiddenByParaField;
}
void SwpHints::NoteInHistory( SwTextAttr *pAttr, const bool bNew )
@@ -3314,8 +3309,8 @@ void SwpHints::DeleteAtPos( const size_t nPos )
const_cast<SwDDEFieldType*>(static_cast<const SwDDEFieldType*>(pFieldTyp))->DecRefCnt();
pTextField->ChgTextNode(nullptr);
}
- else if ( m_bHasHiddenParaField &&
- RES_HIDDENPARAFLD == pFieldTyp->Which() )
+ else if ( m_bHiddenByParaField &&
+ m_rParent.FieldCanHidePara(pFieldTyp->Which()))
{
m_bCalcHiddenParaField = true;
}
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 2e5ba8c3e656..8e8f68c5b5b5 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -917,6 +917,26 @@ void SwViewShell::SetSubtractFlysAnchoredAtFlys(bool bSubtractFlysAnchoredAtFlys
rIDSA.set(DocumentSettingId::SUBTRACT_FLYS, bSubtractFlysAnchoredAtFlys);
}
+void SwViewShell::SetEmptyDbFieldHidesPara(bool bEmptyDbFieldHidesPara)
+{
+ IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
+ if (rIDSA.get(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA) != bEmptyDbFieldHidesPara)
+ {
+ SwWait aWait(*GetDoc()->GetDocShell(), true);
+ rIDSA.set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA, bEmptyDbFieldHidesPara);
+ StartAction();
+ GetDoc()->getIDocumentState().SetModified();
+ for (auto* pFieldType : *GetDoc()->getIDocumentFieldsAccess().GetFieldTypes())
+ {
+ if (pFieldType->Which() == RES_DBFLD)
+ {
+ pFieldType->ModifyNotification(nullptr, nullptr);
+ }
+ }
+ EndAction();
+ }
+}
+
void SwViewShell::Reformat()
{
SwWait aWait( *GetDoc()->GetDocShell(), true );
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index c06c7453f62f..7788fcf16132 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -605,6 +605,32 @@ void SwXMLImport::startDocument()
m_bOrganizerMode = true;
}
}
+
+ // default document properties
+ const OUString sDefSettings("DefaultDocumentSettings");
+ if (xPropertySetInfo->hasPropertyByName(sDefSettings))
+ {
+ aAny = xImportInfo->getPropertyValue(sDefSettings);
+ Sequence<PropertyValue> aProps;
+ if (aAny >>= aProps)
+ {
+ Reference<lang::XMultiServiceFactory> xFac(GetModel(), UNO_QUERY);
+ Reference<XPropertySet> xProps(
+ xFac->createInstance("com.sun.star.document.Settings"), UNO_QUERY);
+ Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
+
+ if (xProps.is() && xInfo.is())
+ {
+ for (const auto& rProp : aProps)
+ {
+ if (xInfo->hasPropertyByName(rProp.Name))
+ {
+ xProps->setPropertyValue(rProp.Name, rProp.Value);
+ }
+ }
+ }
+ }
+ }
}
// There only is a text cursor by now if we are in insert mode. In any
diff --git a/sw/source/ui/config/optcomp.cxx b/sw/source/ui/config/optcomp.cxx
index 65c826fd62ed..3849f900168f 100644
--- a/sw/source/ui/config/optcomp.cxx
+++ b/sw/source/ui/config/optcomp.cxx
@@ -58,6 +58,7 @@ struct CompatibilityItem
bool m_bExpandWordSpace;
bool m_bProtectForm;
bool m_bSubtractFlysAnchoredAtFlys;
+ bool m_bEmptyDbFieldHidesPara;
bool m_bIsDefault;
CompatibilityItem( const OUString& _rName, const OUString& _rModule,
@@ -65,7 +66,7 @@ struct CompatibilityItem
bool _bUseOurTabStops, bool _bNoExtLeading, bool _bUseLineSpacing,
bool _bAddTableSpacing, bool _bUseObjPos, bool _bUseOurTextWrapping,
bool _bConsiderWrappingStyle, bool _bExpandWordSpace, bool _bProtectForm, bool _bSubtractFlysAnchoredAtFlys,
- bool _bIsDefault ) :
+ bool _bEmptyDbFieldHidesPara, bool _bIsDefault ) :
m_sName ( _rName ),
m_sModule ( _rModule ),
@@ -82,6 +83,7 @@ struct CompatibilityItem
m_bExpandWordSpace ( _bExpandWordSpace ),
m_bProtectForm ( _bProtectForm),
m_bSubtractFlysAnchoredAtFlys ( _bSubtractFlysAnchoredAtFlys),
+ m_bEmptyDbFieldHidesPara (_bEmptyDbFieldHidesPara),
m_bIsDefault ( _bIsDefault ) {}
};
@@ -104,7 +106,7 @@ SwCompatibilityOptPage::SwCompatibilityOptPage(vcl::Window* pParent, const SfxIt
get(m_pOptionsLB, "options");
get(m_pDefaultPB, "default");
- for (sal_Int32 nId = COPT_USE_PRINTERDEVICE; nId <= COPT_SUBTRACT_FLYS_ANCHORED_AT_FLYS; ++nId)
+ for (sal_Int32 nId = COPT_USE_PRINTERDEVICE; nId <= COPT_EMPTY_DB_FIELD_HIDES_PARA; ++nId)
{
const OUString sEntry = m_pFormattingLB->GetEntry(nId);
SvTreeListEntry* pEntry = m_pOptionsLB->SvTreeListBox::InsertEntry( sEntry );
@@ -156,7 +158,8 @@ sal_uLong convertBools2Ulong_Impl
bool _bConsiderWrappingStyle,
bool _bExpandWordSpace,
bool _bProtectForm,
- bool bSubtractFlysAnchoredAtFlys
+ bool bSubtractFlysAnchoredAtFlys,
+ bool bEmptyDbFieldHidesPara
)
{
sal_uLong nRet = 0;
@@ -200,6 +203,9 @@ sal_uLong convertBools2Ulong_Impl
nSetBit = nSetBit << 1;
if (bSubtractFlysAnchoredAtFlys)
nRet |= nSetBit;
+ nSetBit = nSetBit << 1;
+ if (bEmptyDbFieldHidesPara)
+ nRet |= nSetBit;
return nRet;
}
@@ -242,6 +248,7 @@ void SwCompatibilityOptPage::InitControls( const SfxItemSet& rSet )
bool bExpandWordSpace = false;
bool bProtectForm = false;
bool bSubtractFlysAnchoredAtFlys = false;
+ bool bEmptyDbFieldHidesPara = true;
const sal_Int32 nCount = aList.getLength();
for ( sal_Int32 i = 0; i < nCount; ++i )
{
@@ -280,6 +287,8 @@ void SwCompatibilityOptPage::InitControls( const SfxItemSet& rSet )
aValue.Value >>= bProtectForm;
else if ( aValue.Name == COMPATIBILITY_PROPERTYNAME_SUBTRACT_FLYS_ANCHORED_AT_FLYS )
aValue.Value >>= bSubtractFlysAnchoredAtFlys;
+ else if ( aValue.Name == COMPATIBILITY_PROPERTYNAME_EMPTY_DB_FIELD_HIDES_PARA )
+ aValue.Value >>= bEmptyDbFieldHidesPara;
}
const bool bIsUserEntry = sName == "_user";
@@ -290,7 +299,7 @@ void SwCompatibilityOptPage::InitControls( const SfxItemSet& rSet )
bAddSpacingAtPages, bUseOurTabStops, bNoExtLeading,
bUseLineSpacing, bAddTableSpacing, bUseObjPos,
bUseOurTextWrapping, bConsiderWrappingStyle, bExpandWordSpace, bProtectForm, bSubtractFlysAnchoredAtFlys,
- bIsDefaultEntry );
+ bEmptyDbFieldHidesPara, bIsDefaultEntry );
m_pImpl->m_aList.push_back( aItem );
if ( aItem.m_bIsDefault )
@@ -315,7 +324,8 @@ void SwCompatibilityOptPage::InitControls( const SfxItemSet& rSet )
bUsePrtMetrics, bAddSpacing, bAddSpacingAtPages,
bUseOurTabStops, bNoExtLeading, bUseLineSpacing,
bAddTableSpacing, bUseObjPos, bUseOurTextWrapping,
- bConsiderWrappingStyle, bExpandWordSpace, bProtectForm, bSubtractFlysAnchoredAtFlys );
+ bConsiderWrappingStyle, bExpandWordSpace, bProtectForm, bSubtractFlysAnchoredAtFlys,
+ bEmptyDbFieldHidesPara);
m_pFormattingLB->SetEntryData( nPos, reinterpret_cast<void*>((sal_IntPtr)nOptions) );
}
@@ -359,6 +369,8 @@ IMPL_LINK_NOARG(SwCompatibilityOptPage, UseAsDefaultHdl, Button*, void)
case COPT_CONSIDER_WRAPPINGSTYLE: pItem->m_bConsiderWrappingStyle = bChecked; break;
case COPT_EXPAND_WORDSPACE: pItem->m_bExpandWordSpace = bChecked; break;
case COPT_PROTECT_FORM: pItem->m_bProtectForm = bChecked; break;
+ case COPT_SUBTRACT_FLYS_ANCHORED_AT_FLYS: pItem->m_bSubtractFlysAnchoredAtFlys = bChecked; break;
+ case COPT_EMPTY_DB_FIELD_HIDES_PARA: pItem->m_bEmptyDbFieldHidesPara = bChecked; break;
default:
{
OSL_FAIL("SwCompatibilityOptPage::UseAsDefaultHdl(): wrong option" );
@@ -404,7 +416,8 @@ sal_uLong SwCompatibilityOptPage::GetDocumentOptions() const
rIDocumentSettingAccess.get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION),
!rIDocumentSettingAccess.get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK),
rIDocumentSettingAccess.get(DocumentSettingId::PROTECT_FORM),
- rIDocumentSettingAccess.get( DocumentSettingId::SUBTRACT_FLYS ));
+ rIDocumentSettingAccess.get( DocumentSettingId::SUBTRACT_FLYS ),
+ rIDocumentSettingAccess.get( DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA ) );
}
return nRet;
}
@@ -420,7 +433,8 @@ void SwCompatibilityOptPage::WriteOptions()
pItem->m_bNoExtLeading, pItem->m_bUseLineSpacing,
pItem->m_bAddTableSpacing, pItem->m_bUseObjPos,
pItem->m_bUseOurTextWrapping, pItem->m_bConsiderWrappingStyle,
- pItem->m_bExpandWordSpace, pItem->m_bProtectForm, pItem->m_bSubtractFlysAnchoredAtFlys );
+ pItem->m_bExpandWordSpace, pItem->m_bProtectForm, pItem->m_bSubtractFlysAnchoredAtFlys,
+ pItem->m_bEmptyDbFieldHidesPara);
}
VclPtr<SfxTabPage> SwCompatibilityOptPage::Create( vcl::Window* pParent, const SfxItemSet* rAttrSet )
@@ -503,6 +517,11 @@ bool SwCompatibilityOptPage::FillItemSet( SfxItemSet* )
m_pWrtShell->SetSubtractFlysAnchoredAtFlys( bChecked );
bModified = true;
}
+ else if ( COPT_EMPTY_DB_FIELD_HIDES_PARA == nOption )
+ {
+ m_pWrtShell->SetEmptyDbFieldHidesPara( bChecked );
+ bModified = true;
+ }
}
nSavedOptions = nSavedOptions >> 1;
diff --git a/sw/source/uibase/app/docshini.cxx b/sw/source/uibase/app/docshini.cxx
index 23361fcff200..0fc42d629273 100644
--- a/sw/source/uibase/app/docshini.cxx
+++ b/sw/source/uibase/app/docshini.cxx
@@ -89,6 +89,7 @@
#include <globals.hrc>
#include <unochart.hxx>
#include <drawdoc.hxx>
+#include <DocumentSettingManager.hxx>
#include <svx/CommonStyleManager.hxx>
@@ -492,14 +493,6 @@ bool SwDocShell::Load( SfxMedium& rMedium )
{
bool bRet = false;
- // If this is an ODF file being loaded, then by default, use legacy processing
- // for tdf#99729 (if required, it will be overriden in *::ReadUserDataSequence())
- if (IsOwnStorageFormat(rMedium))
- {
- if (m_pDoc && m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
- m_pDoc->getIDocumentDrawModelAccess().GetDrawModel()->SetAnchoredTextOverflowLegacy(true);
- }
-
if (SfxObjectShell::Load(rMedium))
{
comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
@@ -511,6 +504,19 @@ bool SwDocShell::Load( SfxMedium& rMedium )
AddLink(); // set Link and update Data!!
+ // Define some settings for legacy ODF files that have different default values now
+ // (if required, they will be overridden later when settings will be read)
+ if (IsOwnStorageFormat(rMedium))
+ {
+ // legacy processing for tdf#99729
+ if (m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
+ m_pDoc->getIDocumentDrawModelAccess().GetDrawModel()->SetAnchoredTextOverflowLegacy(
+ true);
+ // legacy behaviour (not hiding paragraph) for Database (MailMerge) fields
+ m_pDoc->GetDocumentSettingManager().set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA,
+ false);
+ }
+
// Loading
// for MD
OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" );
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx
index 3302d1bc2f1e..557a14bfd6e2 100644
--- a/sw/source/uibase/uno/SwXDocumentSettings.cxx
+++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx
@@ -136,6 +136,7 @@ enum SwDocumentSettingsPropertyHandles
HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING,
HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE,
HANDLE_SUBTRACT_FLYS,
+ HANDLE_EMPTY_DB_FIELD_HIDES_PARA,
};
static MasterPropertySetInfo * lcl_createSettingsInfo()
@@ -212,6 +213,7 @@ static MasterPropertySetInfo * lcl_createSettingsInfo()
{ OUString("ApplyParagraphMarkFormatToNumbering"), HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, cppu::UnoType<bool>::get(), 0},
{ OUString("PropLineSpacingShrinksFirstLine"), HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE, cppu::UnoType<bool>::get(), 0},
{ OUString("SubtractFlysAnchoredAtFlys"), HANDLE_SUBTRACT_FLYS, cppu::UnoType<bool>::get(), 0},
+ { OUString("EmptyDbFieldHidesPara"), HANDLE_EMPTY_DB_FIELD_HIDES_PARA, cppu::UnoType<bool>::get(), 0 },
/*
* As OS said, we don't have a view when we need to set this, so I have to
* find another solution before adding them to this property set - MTG
@@ -863,6 +865,16 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf
}
}
break;
+ case HANDLE_EMPTY_DB_FIELD_HIDES_PARA:
+ {
+ bool bTmp;
+ if (rValue >>= bTmp)
+ {
+ mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA,
+ bTmp);
+ }
+ }
+ break;
default:
throw UnknownPropertyException();
}
@@ -1277,6 +1289,12 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf
rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS);
}
break;
+ case HANDLE_EMPTY_DB_FIELD_HIDES_PARA:
+ {
+ rValue <<= mpDoc->getIDocumentSettingAccess().get(
+ DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA);
+ }
+ break;
default:
throw UnknownPropertyException();
}
diff --git a/sw/uiconfig/swriter/ui/optcompatpage.ui b/sw/uiconfig/swriter/ui/optcompatpage.ui
index 9675da0782be..d73ec394caba 100644
--- a/sw/uiconfig/swriter/ui/optcompatpage.ui
+++ b/sw/uiconfig/swriter/ui/optcompatpage.ui
@@ -66,6 +66,7 @@
<item translatable="yes">Expand word space on lines with manual line breaks in justified paragraphs</item>
<item translatable="yes">Protect form</item>
<item translatable="yes">Use LibreOffice 4.3 anchoring paint order (in current document)</item>
+ <item translatable="yes">A database field (e.g., MailMerge) with empty value hides its paragraph</item>
<item translatable="yes">&lt;User settings&gt;</item>
</items>
</object>