diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2023-02-16 19:39:33 +0100 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2023-02-24 07:32:30 +0000 |
commit | 0168e1eb65103afde24d4a2a62175946b1c0d33e (patch) | |
tree | 015de37ef7b58bf444655b653a4b1e558614f27f | |
parent | db115bec9254417ef7a3faf687478fe5424ab378 (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.hxx | 3 | ||||
-rw-r--r-- | sw/inc/ndtxt.hxx | 10 | ||||
-rw-r--r-- | sw/inc/paratr.hxx | 9 | ||||
-rw-r--r-- | sw/qa/extras/odfexport/data/WordTest_edit.odt | bin | 0 -> 6496 bytes | |||
-rw-r--r-- | sw/qa/extras/odfexport/odfexport2.cxx | 163 | ||||
-rw-r--r-- | sw/source/core/doc/docfmt.cxx | 13 | ||||
-rw-r--r-- | sw/source/core/doc/fmtcol.cxx | 20 | ||||
-rw-r--r-- | sw/source/core/layout/frmtool.cxx | 1 | ||||
-rw-r--r-- | sw/source/core/text/itrcrsr.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/txtnode/ndtxt.cxx | 94 | ||||
-rw-r--r-- | sw/source/core/txtnode/thints.cxx | 17 | ||||
-rw-r--r-- | sw/source/filter/ww8/wrtw8nds.cxx | 14 | ||||
-rw-r--r-- | sw/source/filter/ww8/ww8par6.cxx | 3 | ||||
-rw-r--r-- | sw/source/uibase/app/docstyle.cxx | 17 |
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 Binary files differnew file mode 100644 index 000000000000..4c14295e930d --- /dev/null +++ b/sw/qa/extras/odfexport/data/WordTest_edit.odt 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); + } } } } |