diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 773d54f79318..00d0d5f349e1 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1902,6 +1902,7 @@ namespace xmloff::token {
XML_STRUCTURE_PROTECTED,
XML_STYLE,
XML_STYLE_NAME,
+ XML_STYLE_REF,
XML_STYLES,
XML_STYLESHEET,
XML_SUB_TABLE,
diff --git a/offapi/com/sun/star/text/ReferenceFieldSource.idl b/offapi/com/sun/star/text/ReferenceFieldSource.idl
index 1892fdc04cd8..91295fef2844 100644
--- a/offapi/com/sun/star/text/ReferenceFieldSource.idl
+++ b/offapi/com/sun/star/text/ReferenceFieldSource.idl
@@ -44,6 +44,11 @@ published constants ReferenceFieldSource
/** The source is an endnote.
*/
const short ENDNOTE = 4;
+
+ /** The source is a style.
+ @since LibreOffice 24.2
+ */
+ const short STYLE = 5;
};
diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index 6b52ab7307df..ec0a86afaae4 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -2179,6 +2179,29 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
+
+
+
+
+
+
+
+
+ text
+ direction
+ number
+ number-no-superior
+ number-all-superior
+
+
+
+
+
+
+
+
+
+
diff --git a/sw/inc/fldref.hrc b/sw/inc/fldref.hrc
index d28a1ea43cb5..a48d2d4e4a06 100644
--- a/sw/inc/fldref.hrc
+++ b/sw/inc/fldref.hrc
@@ -31,6 +31,7 @@ const TranslateId FLD_REF_PAGE_TYPES[] =
NC_("fldrefpage|liststore1", "Endnotes"),
NC_("fldrefpage|liststore1", "Headings"),
NC_("fldrefpage|liststore1", "Numbered Paragraphs"),
+ NC_("fldrefpage|liststore1", "Styles"),
};
#endif
diff --git a/sw/inc/reffld.hxx b/sw/inc/reffld.hxx
index 931441d27725..bf9d563ab2ac 100644
--- a/sw/inc/reffld.hxx
+++ b/sw/inc/reffld.hxx
@@ -26,8 +26,10 @@
class SfxPoolItem;
class SwDoc;
class SwTextNode;
+class SwContentFrame;
class SwTextField;
class SwRootFrame;
+class SwFrame;
bool IsFrameBehind( const SwTextNode& rMyNd, sal_Int32 nMySttPos,
const SwTextNode& rBehindNd, sal_Int32 nSttPos );
@@ -39,7 +41,8 @@ enum REFERENCESUBTYPE
REF_BOOKMARK,
REF_OUTLINE,
REF_FOOTNOTE,
- REF_ENDNOTE
+ REF_ENDNOTE,
+ REF_STYLE
};
enum REFERENCEMARK
@@ -80,7 +83,8 @@ public:
static SwTextNode* FindAnchor( SwDoc* pDoc, const OUString& rRefMark,
sal_uInt16 nSubType, sal_uInt16 nSeqNo,
sal_Int32* pStt, sal_Int32* pEnd = nullptr,
- SwRootFrame const* pLayout = nullptr);
+ SwRootFrame const* pLayout = nullptr,
+ SwTextNode* pSelf = nullptr, SwFrame* pFrame = nullptr);
void UpdateGetReferences();
};
@@ -111,11 +115,13 @@ public:
// #i81002#
/** The instance, which represents the text attribute for the
instance, has to be passed to the method.
- This instance is needed for the reference format type REF_UPDOWN
- and REF_NUMBER.
+ This instance is needed for the reference format type REF_UPDOWN, REF_NUMBER
+ and REF_STYLE.
Note: This instance may be NULL (field in Undo/Redo). This will cause
no update for these reference format types. */
- void UpdateField( const SwTextField* pFieldTextAttr );
+ void UpdateField( const SwTextField* pFieldTextAttr, SwFrame* pFrame );
+ void UpdateField( const SwTextField* pFieldTextAttr, SwFrame* pFrame,
+ const SwRootFrame* const pLayout, OUString& rText );
void SetExpand( const OUString& rStr );
@@ -126,9 +132,9 @@ public:
// --> #i81002#
bool IsRefToHeadingCrossRefBookmark() const;
bool IsRefToNumItemCrossRefBookmark() const;
- const SwTextNode* GetReferencedTextNode() const;
+ const SwTextNode* GetReferencedTextNode(SwTextNode* pTextNode, SwFrame* pFrame) const;
// #i85090#
- OUString GetExpandedTextOfReferencedTextNode(SwRootFrame const& rLayout) const;
+ OUString GetExpandedTextOfReferencedTextNode(SwRootFrame const& rLayout, SwTextNode* pTextNode, SwFrame* pFrame) const;
/// Get/set SequenceNo (of interest only for REF_SEQUENCEFLD).
sal_uInt16 GetSeqNo() const { return m_nSeqNo; }
@@ -138,6 +144,8 @@ public:
virtual OUString GetPar1() const override;
virtual void SetPar1(const OUString& rStr) override;
+ void SetText(OUString sText, SwRootFrame* pLayout);
+
virtual OUString GetPar2() const override;
virtual bool QueryValue( css::uno::Any& rVal, sal_uInt16 nWhichId ) const override;
virtual bool PutValue( const css::uno::Any& rVal, sal_uInt16 nWhichId ) override;
diff --git a/sw/qa/core/fields/data/tdf86790.docx b/sw/qa/core/fields/data/tdf86790.docx
new file mode 100644
index 000000000000..a45c03f6b898
Binary files /dev/null and b/sw/qa/core/fields/data/tdf86790.docx differ
diff --git a/sw/qa/core/fields/fields.cxx b/sw/qa/core/fields/fields.cxx
index f2fdd808734f..158e1c35dc2b 100644
--- a/sw/qa/core/fields/fields.cxx
+++ b/sw/qa/core/fields/fields.cxx
@@ -7,6 +7,36 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
@@ -132,6 +162,204 @@ CPPUNIT_TEST_FIXTURE(Test, testChapterFieldsFollowedBy)
CPPUNIT_ASSERT_EQUAL(sValue, xField->getPresentation(false));
}
}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf86790)
+{
+ loadFromURL(u"tdf86790.docx");
+
+ uno::Reference xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference xFieldsAccess(
+ xTextFieldsSupplier->getTextFields());
+ uno::Reference xFields(xFieldsAccess->createEnumeration());
+
+ // Similarly to testChapterFieldsFollowedBy, the fields are enumerated with #1 first and everything else in reverse order
+ std::vector> aFieldValues = {
+ { " Heading 1", "1" }, // #1
+ { " foobar", "22.2" }, // #5
+ { " foobar", "4" }, // #4
+ { " Heading 2", "1.1" }, // #3
+ { " Heading 2", "1.1" }, // #2
+ };
+
+ for (const auto& sValue : aFieldValues)
+ {
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+ uno::Reference xField(xFields->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sValue.first, xField->getPresentation(true));
+ CPPUNIT_ASSERT_EQUAL(sValue.second, xField->getPresentation(false));
+ }
+}
+
+/// If there is referenced text both above and below, STYLEREF searches up
+CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchUp)
+{
+ createSwDoc();
+
+ uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference xText = xTextDocument->getText();
+
+ uno::Reference xCursor = xText->createTextCursor();
+ uno::Reference xCursorPropertySet(xCursor, uno::UNO_QUERY);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading far above field", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading above field", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ uno::Reference xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference xField(
+ xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
+
+ uno::Reference xFieldPropertySet(xField, uno::UNO_QUERY);
+ xFieldPropertySet->setPropertyValue("ReferenceFieldSource",
+ uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
+ xFieldPropertySet->setPropertyValue("ReferenceFieldPart",
+ uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
+ xFieldPropertySet->setPropertyValue("SourceName", uno::Any(OUString("Heading 1")));
+
+ uno::Reference xFieldCursor = xText->createTextCursor();
+
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading below field", false);
+
+ xField->attach(xFieldCursor);
+ CPPUNIT_ASSERT_EQUAL(OUString("Heading above field"), xField->getPresentation(false));
+}
+
+/// If there is referenced text both above and below, STYLEREF searches down
+CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchDown)
+{
+ createSwDoc();
+
+ uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference xText = xTextDocument->getText();
+
+ uno::Reference xCursor = xText->createTextCursor();
+ uno::Reference xCursorPropertySet(xCursor, uno::UNO_QUERY);
+
+ uno::Reference xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference xField(
+ xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
+
+ uno::Reference xFieldPropertySet(xField, uno::UNO_QUERY);
+ xFieldPropertySet->setPropertyValue("ReferenceFieldSource",
+ uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
+ xFieldPropertySet->setPropertyValue("ReferenceFieldPart",
+ uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
+ xFieldPropertySet->setPropertyValue("SourceName", uno::Any(OUString("Heading 1")));
+
+ uno::Reference xFieldCursor = xText->createTextCursor();
+
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading below field", false);
+
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading far below field", false);
+
+ xField->attach(xFieldCursor);
+ CPPUNIT_ASSERT_EQUAL(OUString("Heading below field"), xField->getPresentation(false));
+}
+
+/// STYLEREFs in marginals (headers or footers) should search in the page they are on first, regardless if there is anything above them
+CPPUNIT_TEST_FIXTURE(Test, testMarginalStyleRef)
+{
+ createSwDoc();
+
+ uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference xText = xTextDocument->getText();
+
+ uno::Reference xCursor = xText->createTextCursor();
+ uno::Reference xCursorPropertySet(xCursor, uno::UNO_QUERY);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Top heading on page", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Bottom heading on page", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ uno::Reference xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference xField(
+ xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
+
+ uno::Reference xStyleFamiliesSupplier(mxComponent,
+ uno::UNO_QUERY);
+ uno::Reference xParagraphStylesContainer(
+ xStyleFamiliesSupplier->getStyleFamilies()->getByName("PageStyles"), uno::UNO_QUERY);
+
+ uno::Reference xPagePropertySet(
+ xParagraphStylesContainer->getByName("Standard"), uno::UNO_QUERY);
+
+ xPagePropertySet->setPropertyValue("FooterIsOn", uno::Any(true));
+ uno::Reference xFooterText(xPagePropertySet->getPropertyValue("FooterText"),
+ uno::UNO_QUERY);
+
+ uno::Reference xFieldPropertySet(xField, uno::UNO_QUERY);
+ xFieldPropertySet->setPropertyValue("ReferenceFieldSource",
+ uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
+ xFieldPropertySet->setPropertyValue("ReferenceFieldPart",
+ uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
+ xFieldPropertySet->setPropertyValue("SourceName", uno::Any(OUString("Heading 1")));
+
+ uno::Reference xFooterCursor = xFooterText->createTextCursor();
+ xField->attach(xFooterCursor);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Top heading on page"), xField->getPresentation(false));
+}
+
+/// STYLEREFs in footnotes should search from the point of the reference mark
+CPPUNIT_TEST_FIXTURE(Test, testFootnoteStyleRef)
+{
+ createSwDoc();
+
+ uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference xText = xTextDocument->getText();
+
+ uno::Reference xCursor = xText->createTextCursor();
+ uno::Reference xCursorPropertySet(xCursor, uno::UNO_QUERY);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading far above reference mark", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading above reference mark", false);
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+
+ uno::Reference xFactory(mxComponent, uno::UNO_QUERY);
+
+ uno::Reference xFootnote(
+ xFactory->createInstance("com.sun.star.text.Footnote"), uno::UNO_QUERY);
+ xFootnote->setLabel("Style reference mark");
+ xText->insertTextContent(xCursor, xFootnote, false);
+
+ xText->insertControlCharacter(xCursor, text::ControlCharacter::PARAGRAPH_BREAK, false);
+ xCursorPropertySet->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading 1")));
+ xText->insertString(xCursor, "Heading below reference mark", false);
+
+ uno::Reference xField(
+ xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
+
+ uno::Reference xFieldPropertySet(xField, uno::UNO_QUERY);
+ xFieldPropertySet->setPropertyValue("ReferenceFieldSource",
+ uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
+ xFieldPropertySet->setPropertyValue("ReferenceFieldPart",
+ uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
+ xFieldPropertySet->setPropertyValue("SourceName", uno::Any(OUString("Heading 1")));
+
+ uno::Reference xFootnoteText(xFootnote, uno::UNO_QUERY);
+ uno::Reference xFootnoteCursor = xFootnoteText->createTextCursor();
+ xField->attach(xFootnoteCursor);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Heading above reference mark"), xField->getPresentation(false));
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index cbca150319b7..c4530aa44f6a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -582,7 +582,7 @@ DECLARE_OOXMLEXPORT_TEST(testMultiPageToc, "multi-page-toc.docx")
CPPUNIT_ASSERT_EQUAL(OUString("Table of Contents1"), xTextSection->getName());
// There should be a field in the header as well.
uno::Reference xHeaderText = getProperty< uno::Reference >(getStyles("PageStyles")->getByName("Standard"), "HeaderText");
- CPPUNIT_ASSERT_EQUAL(OUString("TextFieldStart"), getProperty(getRun(getParagraphOfText(1, xHeaderText), 1), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty(getRun(getParagraphOfText(1, xHeaderText), 1), "TextPortionType"));
}
DECLARE_OOXMLEXPORT_TEST(testTextboxTable, "textbox-table.docx")
diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx b/sw/qa/extras/uiwriter/uiwriter8.cxx
index d61bbf289663..8e4869c5d694 100644
--- a/sw/qa/extras/uiwriter/uiwriter8.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter8.cxx
@@ -2454,9 +2454,9 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf128106)
CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_BOOKMARK), fields[0]->GetField()->GetSubType());
CPPUNIT_ASSERT_EQUAL(OUString("bookmarkchapter1_text"),
static_cast(fields[0]->GetField())->GetSetRefName());
- CPPUNIT_ASSERT_EQUAL(OUString("Text"),
- static_cast(fields[0]->GetField())
- ->GetExpandedTextOfReferencedTextNode(*pWrtShell->GetLayout()));
+ CPPUNIT_ASSERT_EQUAL(OUString("Text"), static_cast(fields[0]->GetField())
+ ->GetExpandedTextOfReferencedTextNode(
+ *pWrtShell->GetLayout(), nullptr, nullptr));
CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_BOOKMARK), fields[1]->GetField()->GetSubType());
CPPUNIT_ASSERT(
static_cast(fields[1]->GetField())->IsRefToHeadingCrossRefBookmark());
diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index 578c71b7c21a..87d8dc1f73c5 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -1228,6 +1228,9 @@ OUString SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
case REF_SEQUENCEFLD:
sEntry = static_cast(pField)->GetSetRefName();
break;
+ case REF_STYLE:
+ sEntry = "StyleRef";
+ break;
}
//Get format string
strTypeName = sEntry;
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 3face1677c13..93d22362745c 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -1409,8 +1409,14 @@ bool SwCursorShell::GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType,
SwCursorSaveState aSaveState( *m_pCurrentCursor );
sal_Int32 nPos = -1;
- SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark,
- nSubType, nSeqNo, &nPos, nullptr, GetLayout());
+
+ SwPaM* pCursor = GetCursor();
+ SwPosition* pPos = pCursor->GetPoint();
+ SwTextNode* pRefTextNd = pPos->GetNode().GetTextNode();
+ SwContentFrame* pRefFrame = GetCurrFrame();
+
+ SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor(GetDoc(), rRefMark,
+ nSubType, nSeqNo, &nPos, nullptr, GetLayout(), pRefTextNd, pRefFrame);
if( !pTextNd || !pTextNd->GetNodes().IsDocNodes() )
return false;
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
index d8a66d6ec7a7..442e1644a753 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -65,6 +66,7 @@
#include
#include