summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2023-02-16 19:39:33 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2023-02-24 07:32:30 +0000
commit0168e1eb65103afde24d4a2a62175946b1c0d33e (patch)
tree015de37ef7b58bf444655b653a4b1e558614f27f
parentdb115bec9254417ef7a3faf687478fe5424ab378 (diff)
tdf#78510 sw: combine items from SwTextNode and SwNumFormat
Tweak SwTextFormatColl::AreListLevelIndentsApplicable() and SwTextNode::AreListLevelIndentsApplicable() to return a bitmask so that SvxFirstLineIndentItem and SvxTextLeftMarginItem from paragraph or numbering can be freely combined. Particularly confusing was SwTextNode::GetLeftMarginWithNum() and its baffling usage in SwTextMargin::CtorInitTextMargin(); it appears easiest (if unintuitive) to interpret its return value as a delta to be added to the paragraph's items. This fixes the ODF interop problem. It looks like no compat setting is needed because every OOo/LO generated document should have either both fo:text-indent and fo:margin-left on a paragraph style/list level, or neither. Change-Id: If20b2556bb5ab5d915a2aa6633525bb44a9be33b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147166 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r--sw/inc/fmtcol.hxx3
-rw-r--r--sw/inc/ndtxt.hxx10
-rw-r--r--sw/inc/paratr.hxx9
-rw-r--r--sw/qa/extras/odfexport/data/WordTest_edit.odtbin0 -> 6496 bytes
-rw-r--r--sw/qa/extras/odfexport/odfexport2.cxx163
-rw-r--r--sw/source/core/doc/docfmt.cxx13
-rw-r--r--sw/source/core/doc/fmtcol.cxx20
-rw-r--r--sw/source/core/layout/frmtool.cxx1
-rw-r--r--sw/source/core/text/itrcrsr.cxx10
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx94
-rw-r--r--sw/source/core/txtnode/thints.cxx17
-rw-r--r--sw/source/filter/ww8/wrtw8nds.cxx14
-rw-r--r--sw/source/filter/ww8/ww8par6.cxx3
-rw-r--r--sw/source/uibase/app/docstyle.cxx17
14 files changed, 312 insertions, 62 deletions
diff --git a/sw/inc/fmtcol.hxx b/sw/inc/fmtcol.hxx
index 6a477e1f5ca3..c914a6058ccf 100644
--- a/sw/inc/fmtcol.hxx
+++ b/sw/inc/fmtcol.hxx
@@ -143,7 +143,8 @@ public:
return mbStayAssignedToListLevelOfOutlineStyle;
}
- bool AreListLevelIndentsApplicable() const;
+ ::sw::ListLevelIndents AreListLevelIndentsApplicable() const;
+ bool AreListLevelIndentsApplicableImpl(sal_uInt16 nWhich) const;
void dumpAsXml(xmlTextWriterPtr pWriter) const;
virtual void FormatDropNotify(const SwFormatDrop& rDrop) override
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 0ea123233d69..4b15545b41bc 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -516,9 +516,10 @@ public:
/**
Returns the additional indents of this text node and its numbering.
- @param bTextLeft ???
+ @param bTextLeft return text-left-margin instead of left-margin
+ (include negative first-line-indent, see lrspitem.hxx)
- @return additional indents
+ @return additional num indents - a delta to be added to node's items
*/
tools::Long GetLeftMarginWithNum( bool bTextLeft = false ) const;
@@ -693,9 +694,10 @@ public:
style hierarchy from the paragraph to the paragraph style with the
list style no indent attributes are found.
- @return boolean
+ @return bitmask
*/
- bool AreListLevelIndentsApplicable() const;
+ ::sw::ListLevelIndents AreListLevelIndentsApplicable() const;
+ bool AreListLevelIndentsApplicableImpl(sal_uInt16 nWhich) const;
/** Retrieves the list tab stop position, if the paragraph's list level defines
one and this list tab stop has to merged into the tap stops of the paragraph
diff --git a/sw/inc/paratr.hxx b/sw/inc/paratr.hxx
index c6848491f8e9..9b5f2b156430 100644
--- a/sw/inc/paratr.hxx
+++ b/sw/inc/paratr.hxx
@@ -38,6 +38,7 @@
#include <editeng/forbiddenruleitem.hxx>
#include <editeng/paravertalignitem.hxx>
#include <editeng/pgrditem.hxx>
+#include <o3tl/typed_flags_set.hxx>
class SwTextNode;
class IntlWrapper;
@@ -47,6 +48,9 @@ class IntlWrapper;
class SwFormatDrop;
namespace sw {
+
+ enum class ListLevelIndents { No, FirstLine, LeftMargin };
+
class SW_DLLPUBLIC FormatDropDefiner {
protected:
virtual ~FormatDropDefiner() {};
@@ -55,6 +59,11 @@ namespace sw {
};
}
+namespace o3tl
+{
+ template<> struct typed_flags<sw::ListLevelIndents> : is_typed_flags<sw::ListLevelIndents, 0x03> {};
+}
+
/** If SwFormatDrop is a Client, it is the CharFormat that describes the font for the
DropCaps. If it is not a Client, formatting uses the CharFormat of the paragraph.
If the CharFormat is modified, this change is propagated to the paragraphs
diff --git a/sw/qa/extras/odfexport/data/WordTest_edit.odt b/sw/qa/extras/odfexport/data/WordTest_edit.odt
new file mode 100644
index 000000000000..4c14295e930d
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/WordTest_edit.odt
Binary files differ
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx
index 35e22a59f331..db6c4d4240ae 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -31,6 +31,7 @@
#include <comphelper/propertysequence.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <unoprnms.hxx>
+#include <unotxdoc.hxx>
#include <docsh.hxx>
class Test : public SwModelTestBase
@@ -849,6 +850,168 @@ DECLARE_ODFEXPORT_TEST(testSectionColumnSeparator, "section-columns-separator.fo
CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xColumns, "SeparatorLineIsOn"));
}
+DECLARE_ODFEXPORT_TEST(testTdf78510, "WordTest_edit.odt")
+{
+ uno::Reference<container::XIndexAccess> const xLevels1(
+ getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules"));
+ ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), props1["FirstLineIndent"].get<sal_Int32>());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), props1["IndentAt"].get<sal_Int32>());
+
+ // 1: inherited from paragraph style and overridden by list
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaRightMargin"));
+ // 2: as 1 + paragraph sets firstline
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty<sal_Int32>(getParagraph(2), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(2), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(2), "ParaRightMargin"));
+ // 3: as 1 + paragraph sets textleft
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(3), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(3), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(3), "ParaRightMargin"));
+ // 4: as 1 + paragraph sets firstline, textleft
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(4), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(4), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(4), "ParaRightMargin"));
+ // 5: as 1 + paragraph sets firstline
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(5), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(5), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(5), "ParaRightMargin"));
+ // 6: as 1
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(6), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(6), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(6), "ParaRightMargin"));
+
+ uno::Reference<container::XIndexAccess> const xLevels8(
+ getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(8), "NumberingRules"));
+ ::comphelper::SequenceAsHashMap props8(xLevels8->getByIndex(0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["FirstLineIndent"].get<sal_Int32>());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["IndentAt"].get<sal_Int32>());
+
+ // 8: inherited from paragraph style and overridden by list
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(8), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(8), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(8), "ParaRightMargin"));
+ // 9: as 8 + paragraph sets firstline
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty<sal_Int32>(getParagraph(9), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(9), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(9), "ParaRightMargin"));
+ // 10: as 8 + paragraph sets textleft
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(10), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(10), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(10), "ParaRightMargin"));
+ // 11: as 8 + paragraph sets firstline, textleft
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(11), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(11), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(11), "ParaRightMargin"));
+ // 12: as 8 + paragraph sets firstline
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(12), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(12), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(12), "ParaRightMargin"));
+ // 13: as 8
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(13), "ParaFirstLineIndent"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(13), "ParaLeftMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(13), "ParaRightMargin"));
+
+ // unfortunately it appears that the portions don't have a position
+ // so it's not possible to check the first-line-offset that's applied
+ // (the first-line-indent is computed on the fly in SwTextMargin when
+ // painting)
+ {
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "left", "1134");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds", "left", "1134");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds", "left", "0");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds", "right", "9359");
+
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds", "left", "1701");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds", "left", "-567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds", "right", "9359");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds", "left", "567");
+ assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds", "right", "9359");
+ }
+
+ // now check the positions where text is actually painted -
+ // wonder how fragile this is...
+ // FIXME some platform difference, 1st one is 2306 on Linux, 3087 on WNT ?
+#ifndef WNT
+ {
+ SwDocShell *const pShell(dynamic_cast<SwXTextDocument&>(*mxComponent).GetDocShell());
+ std::shared_ptr<GDIMetaFile> pMetaFile = pShell->GetPreviewMetaFile();
+ MetafileXmlDump aDumper;
+ xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *pMetaFile);
+
+ // 1: inherited from paragraph style and overridden by list
+ // bullet char is extra
+
+ assertXPath(pXmlDoc, "//textarray[1]", "x", "2306");
+ // text is after a tab from list - haven't checked if that is correct?
+ assertXPath(pXmlDoc, "//textarray[2]", "x", "2873");
+ // second line
+ assertXPath(pXmlDoc, "//textarray[3]", "x", "2873");
+ // 2: as 1 + paragraph sets firstline
+ assertXPath(pXmlDoc, "//textarray[4]", "x", "3440");
+ assertXPath(pXmlDoc, "//textarray[5]", "x", "3593");
+ assertXPath(pXmlDoc, "//textarray[6]", "x", "2873");
+ // 3: as 1 + paragraph sets textleft
+ assertXPath(pXmlDoc, "//textarray[7]", "x", "2873");
+ assertXPath(pXmlDoc, "//textarray[8]", "x", "3440");
+ assertXPath(pXmlDoc, "//textarray[9]", "x", "3440");
+ // 4: as 1 + paragraph sets firstline, textleft
+ assertXPath(pXmlDoc, "//textarray[10]", "x", "2306");
+ assertXPath(pXmlDoc, "//textarray[11]", "x", "3440");
+ assertXPath(pXmlDoc, "//textarray[12]", "x", "3440");
+ // 5: as 1 + paragraph sets firstline
+ assertXPath(pXmlDoc, "//textarray[13]", "x", "1739");
+ assertXPath(pXmlDoc, "//textarray[14]", "x", "2873");
+ assertXPath(pXmlDoc, "//textarray[15]", "x", "2873");
+ // 6: as 1
+ assertXPath(pXmlDoc, "//textarray[16]", "x", "2306");
+ assertXPath(pXmlDoc, "//textarray[17]", "x", "2873");
+
+ // 8: inherited from paragraph style and overridden by list
+ assertXPath(pXmlDoc, "//textarray[18]", "x", "2873");
+ assertXPath(pXmlDoc, "//textarray[19]", "x", "3746");
+ assertXPath(pXmlDoc, "//textarray[20]", "x", "2306");
+ // 9: as 8 + paragraph sets firstline
+ assertXPath(pXmlDoc, "//textarray[21]", "x", "3440");
+ assertXPath(pXmlDoc, "//textarray[22]", "x", "3746");
+ assertXPath(pXmlDoc, "//textarray[23]", "x", "2306");
+ // 10: as 8 + paragraph sets textleft
+ assertXPath(pXmlDoc, "//textarray[24]", "x", "4007");
+ assertXPath(pXmlDoc, "//textarray[25]", "x", "4880");
+ assertXPath(pXmlDoc, "//textarray[26]", "x", "3440");
+ // 11: as 8 + paragraph sets firstline, textleft
+ assertXPath(pXmlDoc, "//textarray[27]", "x", "2306");
+ assertXPath(pXmlDoc, "//textarray[28]", "x", "3440");
+ assertXPath(pXmlDoc, "//textarray[29]", "x", "3440");
+ // 12: as 8 + paragraph sets firstline
+ assertXPath(pXmlDoc, "//textarray[30]", "x", "1172");
+ assertXPath(pXmlDoc, "//textarray[31]", "x", "1739");
+ assertXPath(pXmlDoc, "//textarray[32]", "x", "2306");
+ // 13: as 8
+ assertXPath(pXmlDoc, "//textarray[33]", "x", "2873");
+ assertXPath(pXmlDoc, "//textarray[34]", "x", "3746");
+ }
+#endif
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index e990919ed719..f633dd4985b7 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -1653,7 +1653,8 @@ void SwDoc::MoveLeftMargin(const SwPaM& rPam, bool bRight, bool bModulus,
SvxTextLeftMarginItem leftMargin(pTNd->SwContentNode::GetAttr(RES_MARGIN_TEXTLEFT));
// #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx
- if ( pTNd->AreListLevelIndentsApplicable() )
+ ::sw::ListLevelIndents const indents(pTNd->AreListLevelIndentsApplicable());
+ if (indents != ::sw::ListLevelIndents::No)
{
const SwNumRule* pRule = pTNd->GetNumRule();
if ( pRule )
@@ -1664,8 +1665,14 @@ void SwDoc::MoveLeftMargin(const SwPaM& rPam, bool bRight, bool bModulus,
const SwNumFormat& rFormat = pRule->Get(o3tl::narrowing<sal_uInt16>(nListLevel));
if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- leftMargin.SetTextLeft(rFormat.GetIndentAt());
- firstLine.SetTextFirstLineOffset(static_cast<short>(rFormat.GetFirstLineIndent()));
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
+ {
+ leftMargin.SetTextLeft(rFormat.GetIndentAt());
+ }
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ firstLine.SetTextFirstLineOffset(static_cast<short>(rFormat.GetFirstLineIndent()));
+ }
}
}
}
diff --git a/sw/source/core/doc/fmtcol.cxx b/sw/source/core/doc/fmtcol.cxx
index 95cd8754fb44..734fd1312325 100644
--- a/sw/source/core/doc/fmtcol.cxx
+++ b/sw/source/core/doc/fmtcol.cxx
@@ -472,7 +472,21 @@ sal_uInt16 SwTextFormatColl::ResetAllFormatAttr()
return nRet;
}
-bool SwTextFormatColl::AreListLevelIndentsApplicable() const
+::sw::ListLevelIndents SwTextFormatColl::AreListLevelIndentsApplicable() const
+{
+ ::sw::ListLevelIndents ret(::sw::ListLevelIndents::No);
+ if (AreListLevelIndentsApplicableImpl(RES_MARGIN_FIRSTLINE))
+ {
+ ret |= ::sw::ListLevelIndents::FirstLine;
+ }
+ if (AreListLevelIndentsApplicableImpl(RES_MARGIN_TEXTLEFT))
+ {
+ ret |= ::sw::ListLevelIndents::LeftMargin;
+ }
+ return ret;
+}
+
+bool SwTextFormatColl::AreListLevelIndentsApplicableImpl(sal_uInt16 const nWhich) const
{
bool bAreListLevelIndentsApplicable( true );
@@ -481,7 +495,7 @@ bool SwTextFormatColl::AreListLevelIndentsApplicable() const
// no list style applied to paragraph style
bAreListLevelIndentsApplicable = false;
}
- else if ( GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET )
+ else if (GetItemState(nWhich, false ) == SfxItemState::SET)
{
// paragraph style has hard-set indent attributes
bAreListLevelIndentsApplicable = false;
@@ -501,7 +515,7 @@ bool SwTextFormatColl::AreListLevelIndentsApplicable() const
const SwTextFormatColl* pColl = dynamic_cast<const SwTextFormatColl*>(DerivedFrom());
while ( pColl )
{
- if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET )
+ if (pColl->GetAttrSet().GetItemState(nWhich, false) == SfxItemState::SET)
{
// indent attributes found in the paragraph style hierarchy.
bAreListLevelIndentsApplicable = false;
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index bcdb49c292eb..966500ecfeac 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -2257,7 +2257,6 @@ SwBorderAttrs::SwBorderAttrs(const sw::BorderCacheOwner* pOwner, const SwFrame*
m_pFirstLineIndent.reset(m_rAttrSet.GetFirstLineIndent().Clone());
m_pTextLeftMargin.reset(m_rAttrSet.GetTextLeftMargin().Clone());
m_pRightMargin.reset(m_rAttrSet.GetRightMargin().Clone());
- pTextFrame->GetTextNodeForParaProps()->ClearLRSpaceItemDueToListLevelIndents(m_pFirstLineIndent, m_pTextLeftMargin);
assert(m_pFirstLineIndent);
assert(m_pTextLeftMargin);
}
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 7158aa9f0d8f..7963b0aa177c 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -167,7 +167,7 @@ void SwTextMargin::CtorInitTextMargin( SwTextFrame *pNewFrame, SwTextSizeInfo *p
// #i111284#
const SwTextNode *pTextNode = m_pFrame->GetTextNodeForParaProps();
const bool bLabelAlignmentActive = IsLabelAlignmentActive( *pTextNode );
- const bool bListLevelIndentsApplicable = pTextNode->AreListLevelIndentsApplicable();
+ const bool bListLevelIndentsApplicable = pTextNode->AreListLevelIndentsApplicable() != ::sw::ListLevelIndents::No;
const bool bListLevelIndentsApplicableAndLabelAlignmentActive = bListLevelIndentsApplicable && bLabelAlignmentActive;
// Carefully adjust the text formatting ranges.
@@ -192,9 +192,7 @@ void SwTextMargin::CtorInitTextMargin( SwTextFrame *pNewFrame, SwTextSizeInfo *p
// #i95907#
// #i111284#
// rSpace.GetLeft() + rSpace.GetTextLeft();
- ( bListLevelIndentsApplicableAndLabelAlignmentActive
- ? 0
- : (rTextLeftMargin.GetLeft(rFirstLine) - rTextLeftMargin.GetTextLeft()));
+ (rTextLeftMargin.GetLeft(rFirstLine) - rTextLeftMargin.GetTextLeft());
}
else
{
@@ -210,9 +208,7 @@ void SwTextMargin::CtorInitTextMargin( SwTextFrame *pNewFrame, SwTextSizeInfo *p
pNode->GetLeftMarginWithNum() -
// #i95907#
// #i111284#
- ( bListLevelIndentsApplicableAndLabelAlignmentActive
- ? 0
- : (rTextLeftMargin.GetLeft(rFirstLine) - rTextLeftMargin.GetTextLeft()));
+ (rTextLeftMargin.GetLeft(rFirstLine) - rTextLeftMargin.GetTextLeft());
}
else
{
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index ed2065f02c70..63ad3c93bbdd 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -3301,17 +3301,28 @@ tools::Long SwTextNode::GetLeftMarginWithNum( bool bTextLeft ) const
}
else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- if ( AreListLevelIndentsApplicable() )
+ ::sw::ListLevelIndents const indents(AreListLevelIndentsApplicable());
+ // note: the result is *always* added to either the left-margin
+ // or the text-left-margin of the node itself by the caller.
+ // so first, subtract what the caller has computed anyway,
+ // and then add the value according to combination of
+ // list/paragraph items. (this is rather inelegant)
+ SvxFirstLineIndentItem firstLine(GetSwAttrSet().GetFirstLineIndent());
+ SvxTextLeftMarginItem leftMargin(GetSwAttrSet().GetTextLeftMargin());
+ nRet = bTextLeft
+ ? - leftMargin.GetTextLeft()
+ : - leftMargin.GetLeft(firstLine);
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
{
- nRet = rFormat.GetIndentAt();
- // #i90401#
- // Only negative first line indents have consider for the left margin
- if ( !bTextLeft &&
- rFormat.GetFirstLineIndent() < 0 )
- {
- nRet = nRet + rFormat.GetFirstLineIndent();
- }
+ leftMargin.SetTextLeft(rFormat.GetIndentAt());
}
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ firstLine.SetTextFirstLineOffset(rFormat.GetFirstLineIndent());
+ }
+ nRet += bTextLeft
+ ? leftMargin.GetTextLeft()
+ : leftMargin.GetLeft(firstLine);
}
}
@@ -3342,7 +3353,7 @@ bool SwTextNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
}
else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- if ( AreListLevelIndentsApplicable() )
+ if (AreListLevelIndentsApplicable() & ::sw::ListLevelIndents::FirstLine)
{
rFLOffset = rFormat.GetFirstLineIndent();
}
@@ -3382,18 +3393,24 @@ SwTwips SwTextNode::GetAdditionalIndentForStartingNewList() const
}
else if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- if ( AreListLevelIndentsApplicable() )
- {
- nAdditionalIndent = rFormat.GetIndentAt() + rFormat.GetFirstLineIndent();
- }
- else
+ // note: there was an apparent bug here, list GetIndentAt()
+ // was interpreted as left-margin not text-left-margin unlike every
+ // other use of it.
+ ::sw::ListLevelIndents const indents(AreListLevelIndentsApplicable());
+ SvxFirstLineIndentItem const& rFirst(
+ indents & ::sw::ListLevelIndents::FirstLine
+ ? SvxFirstLineIndentItem(rFormat.GetFirstLineIndent(), RES_MARGIN_FIRSTLINE)
+ : GetSwAttrSet().GetFirstLineIndent());
+ SvxTextLeftMarginItem const& rLeft(
+ indents & ::sw::ListLevelIndents::LeftMargin
+ ? SvxTextLeftMarginItem(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT)
+ : GetSwAttrSet().GetTextLeftMargin());
+ nAdditionalIndent = rLeft.GetLeft(rFirst);
+ if (!(indents & ::sw::ListLevelIndents::FirstLine))
{
- SvxFirstLineIndentItem const& rFirst(GetSwAttrSet().GetFirstLineIndent());
- nAdditionalIndent = GetSwAttrSet().GetTextLeftMargin().GetLeft(rFirst);
if (getIDocumentSettingAccess()->get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
{
- nAdditionalIndent = nAdditionalIndent -
- GetSwAttrSet().GetFirstLineIndent().GetTextFirstLineOffset();
+ nAdditionalIndent = nAdditionalIndent - rFirst.GetTextFirstLineOffset();
}
}
}
@@ -3412,7 +3429,8 @@ void SwTextNode::ClearLRSpaceItemDueToListLevelIndents(
std::unique_ptr<SvxFirstLineIndentItem>& o_rFirstLineItem,
std::unique_ptr<SvxTextLeftMarginItem>& o_rTextLeftMarginItem) const
{
- if ( AreListLevelIndentsApplicable() )
+ ::sw::ListLevelIndents const result(AreListLevelIndentsApplicable());
+ if (result != ::sw::ListLevelIndents::No)
{
const SwNumRule* pRule = GetNumRule();
if ( pRule && GetActualListLevel() >= 0 )
@@ -3420,8 +3438,14 @@ void SwTextNode::ClearLRSpaceItemDueToListLevelIndents(
const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- o_rFirstLineItem = std::make_unique<SvxFirstLineIndentItem>(RES_MARGIN_FIRSTLINE);
- o_rTextLeftMarginItem = std::make_unique<SvxTextLeftMarginItem>(RES_MARGIN_TEXTLEFT);
+ if (result & ::sw::ListLevelIndents::FirstLine)
+ {
+ o_rFirstLineItem = std::make_unique<SvxFirstLineIndentItem>(RES_MARGIN_FIRSTLINE);
+ }
+ if (result & ::sw::ListLevelIndents::LeftMargin)
+ {
+ o_rTextLeftMarginItem = std::make_unique<SvxTextLeftMarginItem>(RES_MARGIN_TEXTLEFT);
+ }
}
}
}
@@ -3439,7 +3463,7 @@ tools::Long SwTextNode::GetLeftMarginForTabCalculation() const
const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- if ( AreListLevelIndentsApplicable() )
+ if (AreListLevelIndentsApplicable() & ::sw::ListLevelIndents::LeftMargin)
{
nLeftMarginForTabCalc = rFormat.GetIndentAt();
bLeftMarginForTabCalcSetToListLevelIndent = true;
@@ -4610,9 +4634,23 @@ OUString SwTextNode::GetListId() const
style hierarchy from the paragraph to the paragraph style with the
list style no indent attributes are found.
- @return boolean
+ @return bitmask
*/
-bool SwTextNode::AreListLevelIndentsApplicable() const
+::sw::ListLevelIndents SwTextNode::AreListLevelIndentsApplicable() const
+{
+ ::sw::ListLevelIndents ret(::sw::ListLevelIndents::No);
+ if (AreListLevelIndentsApplicableImpl(RES_MARGIN_FIRSTLINE))
+ {
+ ret |= ::sw::ListLevelIndents::FirstLine;
+ }
+ if (AreListLevelIndentsApplicableImpl(RES_MARGIN_TEXTLEFT))
+ {
+ ret |= ::sw::ListLevelIndents::LeftMargin;
+ }
+ return ret;
+}
+
+bool SwTextNode::AreListLevelIndentsApplicableImpl(sal_uInt16 const nWhich) const
{
bool bAreListLevelIndentsApplicable( true );
@@ -4622,7 +4660,7 @@ bool SwTextNode::AreListLevelIndentsApplicable() const
bAreListLevelIndentsApplicable = false;
}
else if ( HasSwAttrSet() &&
- GetpSwAttrSet()->GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET )
+ GetpSwAttrSet()->GetItemState(nWhich, false) == SfxItemState::SET)
{
// paragraph has hard-set indent attributes
bAreListLevelIndentsApplicable = false;
@@ -4643,7 +4681,7 @@ bool SwTextNode::AreListLevelIndentsApplicable() const
const SwTextFormatColl* pColl = GetTextColl();
while ( pColl )
{
- if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET )
+ if (pColl->GetAttrSet().GetItemState(nWhich, false) == SfxItemState::SET)
{
// indent attributes found in the paragraph style hierarchy.
bAreListLevelIndentsApplicable = false;
@@ -4693,7 +4731,7 @@ bool SwTextNode::GetListTabStopPosition( tools::Long& nListTabStopPosition ) con
{
// tab stop position are treated to be relative to the "before text"
// indent value of the paragraph. Thus, adjust <nListTabStopPos>.
- if ( AreListLevelIndentsApplicable() )
+ if (AreListLevelIndentsApplicable() & ::sw::ListLevelIndents::LeftMargin)
{
nListTabStopPosition -= rFormat.GetIndentAt();
}
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index c31afa4abead..871304abeaa8 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -2112,7 +2112,8 @@ public:
static void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTextNode& rTextNode,
SfxItemSet& rSet )
{
- if ( !rTextNode.AreListLevelIndentsApplicable() )
+ ::sw::ListLevelIndents const indents(rTextNode.AreListLevelIndentsApplicable());
+ if (indents == ::sw::ListLevelIndents::No)
return;
const SwNumRule* pRule = rTextNode.GetNumRule();
@@ -2121,10 +2122,16 @@ static void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTextNode& rTextNode,
const SwNumFormat& rFormat = pRule->Get(o3tl::narrowing<sal_uInt16>(rTextNode.GetActualListLevel()));
if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT);
- SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE);
- rSet.Put(firstLine);
- rSet.Put(leftMargin);
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE);
+ rSet.Put(firstLine);
+ }
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
+ {
+ SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT);
+ rSet.Put(leftMargin);
+ }
}
}
}
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 9bcc4e1e2d30..61d73c32f242 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2970,11 +2970,17 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
// style is applied via paragraph style and the list level
// indent values are not applicable.
if ( pFormat->GetPositionAndSpaceMode() ==
- SvxNumberFormat::LABEL_ALIGNMENT &&
- !rNode.AreListLevelIndentsApplicable() )
+ SvxNumberFormat::LABEL_ALIGNMENT)
{
- oTmpSet->Put(firstLine);
- oTmpSet->Put(leftMargin);
+ ::sw::ListLevelIndents const indents(rNode.AreListLevelIndentsApplicable());
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ oTmpSet->Put(firstLine);
+ }
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
+ {
+ oTmpSet->Put(leftMargin);
+ }
}
}
}
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 4186bfbc3fc8..bdf8607f4d5b 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -4240,7 +4240,8 @@ void SwWW8ImplReader::Read_LR( sal_uInt16 nId, const sal_uInt8* pData, short nLe
// W8ImplReader::RegisterNumFormatOnTextNode).
// Need to apply the list format to the paragraph here.
SwTextNode* pTextNode = m_pPaM->GetPointNode().GetTextNode();
- if( pTextNode && pTextNode->AreListLevelIndentsApplicable() )
+ if (pTextNode
+ && pTextNode->AreListLevelIndentsApplicable() != ::sw::ListLevelIndents::No)
{
SwNumRule * pNumRule = pTextNode->GetNumRule();
if( pNumRule )
diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx
index 9c8f3c3eb4af..6e0ffc5d1cdd 100644
--- a/sw/source/uibase/app/docstyle.cxx
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -1422,7 +1422,8 @@ void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet )
}
OSL_ENSURE( m_pColl, "<SwDocStyleSheet::MergeIndentAttrsOfListStyle(..)> - missing paragraph style");
- if ( !m_pColl->AreListLevelIndentsApplicable() )
+ ::sw::ListLevelIndents const indents(m_pColl->AreListLevelIndentsApplicable());
+ if (indents == ::sw::ListLevelIndents::No)
return;
OSL_ENSURE( m_pColl->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET,
@@ -1437,10 +1438,16 @@ void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet )
const SwNumFormat& rFormat = pRule->Get( 0 );
if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
{
- SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE);
- SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT);
- rSet.Put(firstLine);
- rSet.Put(leftMargin);
+ if (indents & ::sw::ListLevelIndents::FirstLine)
+ {
+ SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE);
+ rSet.Put(firstLine);
+ }
+ if (indents & ::sw::ListLevelIndents::LeftMargin)
+ {
+ SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT);
+ rSet.Put(leftMargin);
+ }
}
}
}