tdf#86790: Add support for a word-style styleref
STYLEREF is a field type in Word which changes its content based on
nearby paragraphs. For example, upon creating a styleref referencing
"Heading 1" you will see the text of the nearest "Heading 1"-styled
paragraph that is above the field.
This patch implements STYLEREF in Writer as a cross-reference. By using
"insert>cross-reference>styles" you'll be presented with a list of
styles. Selecting one and clicking "insert" will create a field which
has text from the "most relevant" instance of the style. To find the
most relevant instance we first search up for paragraphs with the style,
and if there are any we take the closest. If there weren't any, we
search down for paragraphs with the style.
This patch also updates our use of STYLEREF for chapters exported to
docx by using it for all chapters not only those in headers and footers.
This allows us to approximate more chapter field functionality even when
moving between Writer and Word.
Finally, this patch adds some tests for STYLEREF:
- testTdf86790 tests that the "sample file with STYLEREF" document from
tdf#86790 has the correct fields
- testStyleRefSearchUp tests that the STYLEREF searches up when there
are bits of text both above and below it
- testStyleRefSearchDown tests that the STYLEREF searches down when
there are bits of text below it only
- testMarginalStyleRef tests that the STYLEREF searches from the page
top when it is placed in a footer
- testFootnotetyleRef tests that the STYLEREF searches from the
reference mark when it is placed in a footnote
Still TODO:
- [ ] Update documentation
- [ ] Implement reverse-searching (\l) and nondelimiter
suppression (\t)
- Probably these 2 will be in a followup patch
Change-Id: I25dd7a6940abee5651a784b9059fe23b32547d6c
Signed-off-by: Skyler Grey <skyler.grey@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157456
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
This commit is contained in:
committed by
Miklos Vajna
parent
d52982f4b3
commit
32c588dd11
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2179,6 +2179,29 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<!-- TODO no proposal -->
|
||||
<rng:define name="loext-style-reference">
|
||||
<rng:element name="loext:style-ref">
|
||||
<rng:interleave>
|
||||
<rng:ref name="text-common-ref-content"/>
|
||||
<rng:optional>
|
||||
<rng:attribute name="text:reference-format">
|
||||
<rng:choice>
|
||||
<rng:value>text</rng:value>
|
||||
<rng:value>direction</rng:value>
|
||||
<rng:value>number</rng:value>
|
||||
<rng:value>number-no-superior</rng:value>
|
||||
<rng:value>number-all-superior</rng:value>
|
||||
</rng:choice>
|
||||
</rng:attribute>
|
||||
</rng:optional>
|
||||
</rng:interleave>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
<rng:define name="paragraph-content" combine="choice">
|
||||
<rng:ref name="loext-style-reference"/>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="loext-qrcode">
|
||||
<rng:element name="loext:qrcode">
|
||||
<rng:attribute name="office:string-value">
|
||||
|
||||
@@ -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
|
||||
|
||||
+15
-7
@@ -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 <SwTextField> instance, which represents the text attribute for the
|
||||
<SwGetRefField> instance, has to be passed to the method.
|
||||
This <SwTextField> instance is needed for the reference format type REF_UPDOWN
|
||||
and REF_NUMBER.
|
||||
This <SwTextField> 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;
|
||||
|
||||
Binary file not shown.
@@ -7,6 +7,36 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <com/sun/star/beans/PropertyValue.hpp>
|
||||
#include <com/sun/star/frame/XStorable.hpp>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
#include <com/sun/star/container/XIndexAccess.hpp>
|
||||
#include <com/sun/star/text/ControlCharacter.hpp>
|
||||
#include <com/sun/star/text/ReferenceFieldPart.hpp>
|
||||
#include <com/sun/star/text/ReferenceFieldSource.hpp>
|
||||
#include <com/sun/star/text/XFootnote.hpp>
|
||||
#include <com/sun/star/text/XFootnotesSupplier.hpp>
|
||||
#include <com/sun/star/text/XSimpleText.hpp>
|
||||
#include <com/sun/star/text/XTextField.hpp>
|
||||
#include <com/sun/star/text/XTextRange.hpp>
|
||||
#include <com/sun/star/frame/XStorable.hpp>
|
||||
#include <com/sun/star/text/XPageCursor.hpp>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
#include <com/sun/star/beans/XPropertySetInfo.hpp>
|
||||
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
||||
#include <com/sun/star/text/XSimpleText.hpp>
|
||||
#include <com/sun/star/text/XText.hpp>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
#include <com/sun/star/container/XNameContainer.hpp>
|
||||
#include <com/sun/star/text/XPageCursor.hpp>
|
||||
#include <com/sun/star/text/XTextCursor.hpp>
|
||||
#include <com/sun/star/uno/Any.h>
|
||||
#include <com/sun/star/uno/Reference.h>
|
||||
#include <com/sun/star/uno/Sequence.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <sal/types.h>
|
||||
#include <swmodeltestbase.hxx>
|
||||
|
||||
#include <com/sun/star/text/XTextDocument.hpp>
|
||||
@@ -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<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<container::XEnumerationAccess> xFieldsAccess(
|
||||
xTextFieldsSupplier->getTextFields());
|
||||
uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
|
||||
|
||||
// Similarly to testChapterFieldsFollowedBy, the fields are enumerated with #1 first and everything else in reverse order
|
||||
std::vector<std::pair<OUString, OUString>> 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<text::XTextField> 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<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XText> xText = xTextDocument->getText();
|
||||
|
||||
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
||||
uno::Reference<beans::XPropertySet> 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<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XTextField> xField(
|
||||
xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<beans::XPropertySet> 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<text::XTextCursor> 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<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XText> xText = xTextDocument->getText();
|
||||
|
||||
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
||||
uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XTextField> xField(
|
||||
xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<beans::XPropertySet> 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<text::XTextCursor> 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<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XText> xText = xTextDocument->getText();
|
||||
|
||||
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
||||
uno::Reference<beans::XPropertySet> 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<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XTextField> xField(
|
||||
xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent,
|
||||
uno::UNO_QUERY);
|
||||
uno::Reference<container::XNameContainer> xParagraphStylesContainer(
|
||||
xStyleFamiliesSupplier->getStyleFamilies()->getByName("PageStyles"), uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<beans::XPropertySet> xPagePropertySet(
|
||||
xParagraphStylesContainer->getByName("Standard"), uno::UNO_QUERY);
|
||||
|
||||
xPagePropertySet->setPropertyValue("FooterIsOn", uno::Any(true));
|
||||
uno::Reference<text::XText> xFooterText(xPagePropertySet->getPropertyValue("FooterText"),
|
||||
uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<beans::XPropertySet> 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<text::XTextRange> 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<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
||||
uno::Reference<text::XText> xText = xTextDocument->getText();
|
||||
|
||||
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
||||
uno::Reference<beans::XPropertySet> 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<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<text::XFootnote> 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<text::XTextField> xField(
|
||||
xFactory->createInstance("com.sun.star.text.TextField.GetReference"), uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<beans::XPropertySet> 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<text::XSimpleText> xFootnoteText(xFootnote, uno::UNO_QUERY);
|
||||
uno::Reference<text::XTextRange> xFootnoteCursor = xFootnoteText->createTextCursor();
|
||||
xField->attach(xFootnoteCursor);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(OUString("Heading above reference mark"), xField->getPresentation(false));
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
@@ -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<text::XText> xHeaderText = getProperty< uno::Reference<text::XText> >(getStyles("PageStyles")->getByName("Standard"), "HeaderText");
|
||||
CPPUNIT_ASSERT_EQUAL(OUString("TextFieldStart"), getProperty<OUString>(getRun(getParagraphOfText(1, xHeaderText), 1), "TextPortionType"));
|
||||
CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty<OUString>(getRun(getParagraphOfText(1, xHeaderText), 1), "TextPortionType"));
|
||||
}
|
||||
|
||||
DECLARE_OOXMLEXPORT_TEST(testTextboxTable, "textbox-table.docx")
|
||||
|
||||
@@ -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<SwGetRefField const*>(fields[0]->GetField())->GetSetRefName());
|
||||
CPPUNIT_ASSERT_EQUAL(OUString("Text"),
|
||||
static_cast<SwGetRefField const*>(fields[0]->GetField())
|
||||
->GetExpandedTextOfReferencedTextNode(*pWrtShell->GetLayout()));
|
||||
CPPUNIT_ASSERT_EQUAL(OUString("Text"), static_cast<SwGetRefField const*>(fields[0]->GetField())
|
||||
->GetExpandedTextOfReferencedTextNode(
|
||||
*pWrtShell->GetLayout(), nullptr, nullptr));
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt16(REF_BOOKMARK), fields[1]->GetField()->GetSubType());
|
||||
CPPUNIT_ASSERT(
|
||||
static_cast<SwGetRefField const*>(fields[1]->GetField())->IsRefToHeadingCrossRefBookmark());
|
||||
|
||||
@@ -1228,6 +1228,9 @@ OUString SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
|
||||
case REF_SEQUENCEFLD:
|
||||
sEntry = static_cast<const SwGetRefField*>(pField)->GetSetRefName();
|
||||
break;
|
||||
case REF_STYLE:
|
||||
sEntry = "StyleRef";
|
||||
break;
|
||||
}
|
||||
//Get format string
|
||||
strTypeName = sEntry;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <reffld.hxx>
|
||||
#include <expfld.hxx>
|
||||
#include <txtfrm.hxx>
|
||||
#include <notxtfrm.hxx>
|
||||
#include <flyfrm.hxx>
|
||||
#include <pagedesc.hxx>
|
||||
#include <IMark.hxx>
|
||||
@@ -65,6 +66,7 @@
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
using namespace ::com::sun::star::text;
|
||||
@@ -349,11 +351,11 @@ static void lcl_formatReferenceLanguage( OUString& rRefText,
|
||||
SwGetRefField::SwGetRefField( SwGetRefFieldType* pFieldType,
|
||||
OUString aSetRef, OUString aSetReferenceLanguage, sal_uInt16 nSubTyp,
|
||||
sal_uInt16 nSequenceNo, sal_uLong nFormat )
|
||||
: SwField( pFieldType, nFormat ),
|
||||
m_sSetRefName( std::move(aSetRef) ),
|
||||
m_sSetReferenceLanguage( std::move(aSetReferenceLanguage) ),
|
||||
m_nSubType( nSubTyp ),
|
||||
m_nSeqNo( nSequenceNo )
|
||||
: SwField(pFieldType, nFormat),
|
||||
m_sSetRefName(std::move(aSetRef)),
|
||||
m_sSetReferenceLanguage(std::move(aSetReferenceLanguage)),
|
||||
m_nSubType(nSubTyp),
|
||||
m_nSeqNo(nSequenceNo)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -361,6 +363,18 @@ SwGetRefField::~SwGetRefField()
|
||||
{
|
||||
}
|
||||
|
||||
void SwGetRefField::SetText(OUString sText, SwRootFrame* pLayout)
|
||||
{
|
||||
if (pLayout->IsHideRedlines())
|
||||
{
|
||||
m_sTextRLHidden = sText;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sText = sText;
|
||||
}
|
||||
}
|
||||
|
||||
OUString SwGetRefField::GetDescription() const
|
||||
{
|
||||
return SwResId(STR_REFERENCE);
|
||||
@@ -389,13 +403,14 @@ bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const
|
||||
::sw::mark::CrossRefNumItemBookmark::IsLegalName(m_sSetRefName);
|
||||
}
|
||||
|
||||
const SwTextNode* SwGetRefField::GetReferencedTextNode() const
|
||||
const SwTextNode* SwGetRefField::GetReferencedTextNode(SwTextNode* pTextNode, SwFrame* pFrame) const
|
||||
{
|
||||
SwGetRefFieldType *pTyp = dynamic_cast<SwGetRefFieldType*>(GetTyp());
|
||||
if (!pTyp)
|
||||
return nullptr;
|
||||
sal_Int32 nDummy = -1;
|
||||
return SwGetRefFieldType::FindAnchor( &pTyp->GetDoc(), m_sSetRefName, m_nSubType, m_nSeqNo, &nDummy );
|
||||
return SwGetRefFieldType::FindAnchor( &pTyp->GetDoc(), m_sSetRefName, m_nSubType, m_nSeqNo, &nDummy,
|
||||
nullptr, nullptr, pTextNode, pFrame );
|
||||
}
|
||||
|
||||
// strikethrough for tooltips using Unicode combining character
|
||||
@@ -411,9 +426,9 @@ static OUString lcl_formatStringByCombiningCharacter(std::u16string_view sText,
|
||||
|
||||
// #i85090#
|
||||
OUString SwGetRefField::GetExpandedTextOfReferencedTextNode(
|
||||
SwRootFrame const& rLayout) const
|
||||
SwRootFrame const& rLayout, SwTextNode* pTextNode, SwFrame* pFrame) const
|
||||
{
|
||||
const SwTextNode* pReferencedTextNode( GetReferencedTextNode() );
|
||||
const SwTextNode* pReferencedTextNode( GetReferencedTextNode(pTextNode, pFrame) );
|
||||
if ( !pReferencedTextNode )
|
||||
return OUString();
|
||||
|
||||
@@ -481,38 +496,43 @@ static void FilterText(OUString & rText, LanguageType const eLang,
|
||||
}
|
||||
|
||||
// #i81002# - parameter <pFieldTextAttr> added
|
||||
void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr, SwFrame* pFrame )
|
||||
{
|
||||
m_sText.clear();
|
||||
m_sTextRLHidden.clear();
|
||||
|
||||
SwDoc& rDoc = static_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
|
||||
|
||||
for (SwRootFrame const* const pLay : rDoc.GetAllLayouts())
|
||||
{
|
||||
if (pLay->IsHideRedlines())
|
||||
{
|
||||
UpdateField(pFieldTextAttr, pFrame, pLay, m_sTextRLHidden);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateField(pFieldTextAttr, pFrame, pLay, m_sText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SwGetRefField::UpdateField(const SwTextField* pFieldTextAttr, SwFrame* pFrameContainingField,
|
||||
const SwRootFrame* const pLayout, OUString& rText)
|
||||
{
|
||||
SwDoc& rDoc = static_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
|
||||
|
||||
rText.clear();
|
||||
|
||||
// finding the reference target (the number)
|
||||
sal_Int32 nNumStart = -1;
|
||||
sal_Int32 nNumEnd = -1;
|
||||
SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor(
|
||||
&rDoc, m_sSetRefName, m_nSubType, m_nSeqNo, &nNumStart, &nNumEnd
|
||||
&rDoc, m_sSetRefName, m_nSubType, m_nSeqNo, &nNumStart, &nNumEnd,
|
||||
pLayout, pFieldTextAttr ? pFieldTextAttr->GetpTextNode() : nullptr, pFrameContainingField
|
||||
);
|
||||
// not found?
|
||||
if ( !pTextNd )
|
||||
{
|
||||
m_sText = SwViewShell::GetShellRes()->aGetRefField_RefItemNotFound;
|
||||
m_sTextRLHidden = m_sText;
|
||||
return ;
|
||||
}
|
||||
rText = SwViewShell::GetShellRes()->aGetRefField_RefItemNotFound;
|
||||
|
||||
SwRootFrame const* pLayout(nullptr);
|
||||
SwRootFrame const* pLayoutRLHidden(nullptr);
|
||||
for (SwRootFrame const*const pLay : rDoc.GetAllLayouts())
|
||||
{
|
||||
if (pLay->IsHideRedlines())
|
||||
{
|
||||
pLayoutRLHidden = pLay;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLayout = pLay;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// where is the category name (e.g. "Illustration")?
|
||||
@@ -607,18 +627,21 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
SwTextFootnote* const pFootnoteIdx = rDoc.GetFootnoteIdxs()[i];
|
||||
if( m_nSeqNo == pFootnoteIdx->GetSeqRefNo() )
|
||||
{
|
||||
m_sText = pFootnoteIdx->GetFootnote().GetViewNumStr(rDoc, nullptr);
|
||||
m_sTextRLHidden = pFootnoteIdx->GetFootnote().GetViewNumStr(rDoc, pLayoutRLHidden);
|
||||
rText = pFootnoteIdx->GetFootnote().GetViewNumStr(rDoc, pLayout);
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
{
|
||||
lcl_formatReferenceLanguage(m_sText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
lcl_formatReferenceLanguage(m_sTextRLHidden, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
lcl_formatReferenceLanguage(rText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case REF_STYLE:
|
||||
nStart = 0;
|
||||
nEnd = nLen;
|
||||
break;
|
||||
|
||||
case REF_SETREFATTR:
|
||||
nStart = nNumStart;
|
||||
nEnd = nNumEnd;
|
||||
@@ -630,26 +653,32 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
|
||||
if( nStart != nEnd ) // a section?
|
||||
{
|
||||
m_sText = pTextNd->GetExpandText(pLayout, nStart, nEnd - nStart, false, false, false, ExpandMode::HideDeletions);
|
||||
// show the referenced text without the deletions, but if the whole text was
|
||||
// deleted, show the original text for the sake of the comfortable reviewing
|
||||
// (with strikethrough in tooltip, see GetExpandedTextOfReferencedTextNode())
|
||||
if ( m_sText.isEmpty() )
|
||||
m_sText = pTextNd->GetExpandText(pLayout, nStart, nEnd - nStart, false, false, false, ExpandMode(0));
|
||||
|
||||
if (m_nSubType == REF_OUTLINE
|
||||
|| (m_nSubType == REF_SEQUENCEFLD && REF_CONTENT == GetFormat()))
|
||||
if (pLayout->IsHideRedlines())
|
||||
{
|
||||
m_sTextRLHidden = sw::GetExpandTextMerged(
|
||||
pLayoutRLHidden, *pTextNd, false, false, ExpandMode(0));
|
||||
if (m_nSubType == REF_OUTLINE
|
||||
|| (m_nSubType == REF_SEQUENCEFLD && REF_CONTENT == GetFormat()))
|
||||
{
|
||||
rText = sw::GetExpandTextMerged(pLayout, *pTextNd, false, false,
|
||||
ExpandMode(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
rText = pTextNd->GetExpandText(pLayout, nStart, nEnd - nStart, false, false,
|
||||
false, ExpandMode::HideDeletions);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sTextRLHidden = pTextNd->GetExpandText(pLayoutRLHidden,
|
||||
nStart, nEnd - nStart, false, false, false, ExpandMode::HideDeletions);
|
||||
rText = pTextNd->GetExpandText(pLayout, nStart, nEnd - nStart, false, false,
|
||||
false, ExpandMode::HideDeletions);
|
||||
// show the referenced text without the deletions, but if the whole text was
|
||||
// deleted, show the original text for the sake of the comfortable reviewing
|
||||
// (with strikethrough in tooltip, see GetExpandedTextOfReferencedTextNode())
|
||||
if (rText.isEmpty())
|
||||
rText = pTextNd->GetExpandText(pLayout, nStart, nEnd - nStart, false, false,
|
||||
false, ExpandMode(0));
|
||||
}
|
||||
FilterText(m_sText, GetLanguage(), m_sSetReferenceLanguage);
|
||||
FilterText(m_sTextRLHidden, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -657,10 +686,7 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
case REF_PAGE:
|
||||
case REF_PAGE_PGDESC:
|
||||
{
|
||||
auto const func =
|
||||
[this, pTextNd, nNumStart](OUString & rText, SwRootFrame const*const pLay)
|
||||
{
|
||||
SwTextFrame const* pFrame = static_cast<SwTextFrame*>(pTextNd->getLayoutFrame(pLay, nullptr, nullptr));
|
||||
SwTextFrame const* pFrame = static_cast<SwTextFrame*>(pTextNd->getLayoutFrame(pLayout, nullptr, nullptr));
|
||||
SwTextFrame const*const pSave = pFrame;
|
||||
if (pFrame)
|
||||
{
|
||||
@@ -687,35 +713,25 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
lcl_formatReferenceLanguage(rText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
};
|
||||
// sw_redlinehide: currently only one of these layouts will exist,
|
||||
// so the getLayoutFrame will use the same frame in both cases
|
||||
func(m_sText, pLayout);
|
||||
func(m_sTextRLHidden, pLayoutRLHidden);
|
||||
}
|
||||
break;
|
||||
|
||||
case REF_CHAPTER:
|
||||
{
|
||||
// a bit tricky: search any frame
|
||||
SwFrame const* const pFrame = pTextNd->getLayoutFrame(pLayout);
|
||||
if (pFrame)
|
||||
{
|
||||
auto const func =
|
||||
[this, pTextNd](OUString & rText, SwRootFrame const*const pLay)
|
||||
{
|
||||
// a bit tricky: search any frame
|
||||
SwFrame const*const pFrame = pTextNd->getLayoutFrame(pLay);
|
||||
if( pFrame )
|
||||
{
|
||||
SwChapterFieldType aFieldTyp;
|
||||
SwChapterField aField( &aFieldTyp, 0 );
|
||||
aField.SetLevel( MAXLEVEL - 1 );
|
||||
aField.ChangeExpansion( *pFrame, pTextNd, true );
|
||||
rText = aField.GetNumber(pLay);
|
||||
SwChapterFieldType aFieldTyp;
|
||||
SwChapterField aField(&aFieldTyp, 0);
|
||||
aField.SetLevel(MAXLEVEL - 1);
|
||||
aField.ChangeExpansion(*pFrame, pTextNd, true);
|
||||
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
lcl_formatReferenceLanguage(rText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
};
|
||||
func(m_sText, pLayout);
|
||||
func(m_sTextRLHidden, pLayoutRLHidden);
|
||||
rText = aField.GetNumber(pLayout);
|
||||
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
lcl_formatReferenceLanguage(rText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -731,22 +747,19 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
// first a "short" test - in case both are in the same node
|
||||
if( pFieldTextAttr->GetpTextNode() == pTextNd )
|
||||
{
|
||||
m_sText = nNumStart < pFieldTextAttr->GetStart()
|
||||
rText = nNumStart < pFieldTextAttr->GetStart()
|
||||
? aLocaleData.getAboveWord()
|
||||
: aLocaleData.getBelowWord();
|
||||
m_sTextRLHidden = m_sText;
|
||||
break;
|
||||
}
|
||||
|
||||
m_sText = ::IsFrameBehind( *pFieldTextAttr->GetpTextNode(), pFieldTextAttr->GetStart(),
|
||||
rText = ::IsFrameBehind( *pFieldTextAttr->GetpTextNode(), pFieldTextAttr->GetStart(),
|
||||
*pTextNd, nNumStart )
|
||||
? aLocaleData.getAboveWord()
|
||||
: aLocaleData.getBelowWord();
|
||||
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
lcl_formatReferenceLanguage(m_sText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
|
||||
m_sTextRLHidden = m_sText;
|
||||
lcl_formatReferenceLanguage(rText, false, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
break;
|
||||
// #i81002#
|
||||
@@ -758,20 +771,12 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
|
||||
{
|
||||
auto result =
|
||||
MakeRefNumStr(pLayout, pFieldTextAttr->GetTextNode(), *pTextNd, GetFormat());
|
||||
m_sText = result.first;
|
||||
rText = result.first;
|
||||
// for differentiation of Roman numbers and letters in Hungarian article handling
|
||||
bool bClosingParenthesis = result.second;
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
{
|
||||
lcl_formatReferenceLanguage(m_sText, bClosingParenthesis, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
result =
|
||||
MakeRefNumStr(pLayoutRLHidden, pFieldTextAttr->GetTextNode(), *pTextNd, GetFormat());
|
||||
m_sTextRLHidden = result.first;
|
||||
bClosingParenthesis = result.second;
|
||||
if (!m_sSetReferenceLanguage.isEmpty())
|
||||
{
|
||||
lcl_formatReferenceLanguage(m_sTextRLHidden, bClosingParenthesis, GetLanguage(), m_sSetReferenceLanguage);
|
||||
lcl_formatReferenceLanguage(rText, bClosingParenthesis, GetLanguage(), m_sSetReferenceLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -934,6 +939,7 @@ bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
|
||||
case REF_OUTLINE : OSL_FAIL("not implemented"); break;
|
||||
case REF_FOOTNOTE : nSource = ReferenceFieldSource::FOOTNOTE; break;
|
||||
case REF_ENDNOTE : nSource = ReferenceFieldSource::ENDNOTE; break;
|
||||
case REF_STYLE : nSource = ReferenceFieldSource::STYLE; break;
|
||||
}
|
||||
rAny <<= nSource;
|
||||
}
|
||||
@@ -1018,6 +1024,7 @@ bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
|
||||
case ReferenceFieldSource::BOOKMARK : m_nSubType = REF_BOOKMARK ; break;
|
||||
case ReferenceFieldSource::FOOTNOTE : m_nSubType = REF_FOOTNOTE ; break;
|
||||
case ReferenceFieldSource::ENDNOTE : m_nSubType = REF_ENDNOTE ; break;
|
||||
case ReferenceFieldSource::STYLE : m_nSubType = REF_STYLE ; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1115,7 +1122,7 @@ void SwGetRefFieldType::UpdateGetReferences()
|
||||
}
|
||||
|
||||
// #i81002#
|
||||
pGRef->UpdateField(pFormatField->GetTextField());
|
||||
pGRef->UpdateField(pFormatField->GetTextField(), nullptr);
|
||||
}
|
||||
CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
|
||||
}
|
||||
@@ -1166,10 +1173,53 @@ bool IsMarkHintHidden(SwRootFrame const& rLayout,
|
||||
|
||||
} // namespace sw
|
||||
|
||||
SwTextNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const OUString& rRefMark,
|
||||
sal_uInt16 nSubType, sal_uInt16 nSeqNo,
|
||||
sal_Int32* pStt, sal_Int32* pEnd,
|
||||
SwRootFrame const*const pLayout)
|
||||
namespace
|
||||
{
|
||||
enum StyleRefElementType
|
||||
{
|
||||
Default,
|
||||
Reference, /* e.g. footnotes, endnotes */
|
||||
Marginal, /* headers, footers */
|
||||
};
|
||||
|
||||
/// Picks the first text node with a matching style from a double ended queue, starting at the front
|
||||
/// This allows us to use the deque either as a stack or as a queue depending on whether we want to search up or down
|
||||
SwTextNode* SearchForStyleAnchor(SwTextNode* pSelf, const std::deque<SwNode*>& pToSearch,
|
||||
std::u16string_view rStyleName, bool bCaseSensitive = true)
|
||||
{
|
||||
std::deque<SwNode*> pSearching(pToSearch);
|
||||
while (!pSearching.empty())
|
||||
{
|
||||
SwNode* pCurrent = pSearching.front();
|
||||
pSearching.pop_front();
|
||||
|
||||
if (*pCurrent == *pSelf)
|
||||
continue;
|
||||
|
||||
SwTextNode* pTextNode = pCurrent->GetTextNode();
|
||||
if (!pTextNode)
|
||||
continue;
|
||||
|
||||
if (bCaseSensitive)
|
||||
{
|
||||
if (pTextNode->GetFormatColl()->GetName() == rStyleName)
|
||||
return pTextNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pTextNode->GetFormatColl()->GetName().equalsIgnoreAsciiCase(rStyleName))
|
||||
return pTextNode;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SwTextNode* SwGetRefFieldType::FindAnchor(SwDoc* pDoc, const OUString& rRefMark,
|
||||
sal_uInt16 nSubType, sal_uInt16 nSeqNo, sal_Int32* pStt,
|
||||
sal_Int32* pEnd, SwRootFrame const* const pLayout,
|
||||
SwTextNode* pSelf, SwFrame* pContentFrame)
|
||||
{
|
||||
OSL_ENSURE( pStt, "Why did no one check the StartPos?" );
|
||||
|
||||
@@ -1284,6 +1334,250 @@ SwTextNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const OUString& rRefMark
|
||||
}
|
||||
}
|
||||
break;
|
||||
case REF_STYLE:
|
||||
if (!pSelf) break;
|
||||
|
||||
const SwNodes& nodes = pDoc->GetNodes();
|
||||
|
||||
StyleRefElementType elementType = StyleRefElementType::Default;
|
||||
const SwTextNode* pReference = nullptr;
|
||||
|
||||
{ /* Check if we're a footnote/endnote */
|
||||
for (SwTextFootnote* pFootnoteIdx : pDoc->GetFootnoteIdxs())
|
||||
{
|
||||
if (pLayout && pLayout->IsHideRedlines()
|
||||
&& sw::IsFootnoteDeleted(rIDRA, *pFootnoteIdx))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const SwNodeIndex* pIdx = pFootnoteIdx->GetStartNode();
|
||||
if (pIdx)
|
||||
{
|
||||
SwNodeIndex aIdx(*pIdx, 1);
|
||||
SwTextNode* pFootnoteNode = aIdx.GetNode().GetTextNode();
|
||||
if (nullptr == pFootnoteNode)
|
||||
pFootnoteNode
|
||||
= static_cast<SwTextNode*>(pDoc->GetNodes().GoNext(&aIdx));
|
||||
|
||||
if (*pSelf == *pFootnoteNode)
|
||||
{
|
||||
elementType = StyleRefElementType::Reference;
|
||||
pReference = &pFootnoteIdx->GetTextNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pDoc->IsInHeaderFooter(*pSelf))
|
||||
{
|
||||
elementType = StyleRefElementType::Marginal;
|
||||
}
|
||||
|
||||
if (pReference == nullptr)
|
||||
{
|
||||
pReference = pSelf;
|
||||
}
|
||||
|
||||
switch (elementType)
|
||||
{
|
||||
case Marginal:
|
||||
{
|
||||
// For marginals, styleref tries to act on the current page first
|
||||
// 1. Get the page we're on, search it from top to bottom
|
||||
|
||||
Point aPt;
|
||||
std::pair<Point, bool> const tmp(aPt, false);
|
||||
|
||||
if (!pContentFrame) SAL_WARN("xmloff.text", "<SwGetRefFieldType::FindAnchor(..)>: Missing content frame for marginal styleref");
|
||||
const SwPageFrame* pPageFrame = nullptr;
|
||||
|
||||
if (pContentFrame)
|
||||
pPageFrame = pContentFrame->FindPageFrame();
|
||||
|
||||
const SwNode* pPageStart(nullptr);
|
||||
const SwNode* pPageEnd(nullptr);
|
||||
|
||||
if (pPageFrame)
|
||||
{
|
||||
const SwContentFrame* pPageStartFrame = pPageFrame->FindFirstBodyContent();
|
||||
const SwContentFrame* pPageEndFrame = pPageFrame->FindLastBodyContent();
|
||||
|
||||
if (pPageStartFrame) {
|
||||
if (pPageStartFrame->IsTextFrame())
|
||||
{
|
||||
pPageStart = static_cast<const SwTextFrame*>(pPageStartFrame)
|
||||
->GetTextNodeFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
pPageStart
|
||||
= static_cast<const SwNoTextFrame*>(pPageStartFrame)->GetNode();
|
||||
}
|
||||
}
|
||||
|
||||
if (pPageEndFrame) {
|
||||
if (pPageEndFrame->IsTextFrame())
|
||||
{
|
||||
pPageEnd = static_cast<const SwTextFrame*>(pPageEndFrame)
|
||||
->GetTextNodeFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
pPageEnd = static_cast<const SwNoTextFrame*>(pPageEndFrame)->GetNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pPageStart || !pPageEnd)
|
||||
{
|
||||
pPageStart = pReference;
|
||||
pPageEnd = pReference;
|
||||
}
|
||||
|
||||
std::deque<SwNode*> pAbovePage;
|
||||
std::deque<SwNode*> pInPage;
|
||||
std::deque<SwNode*> pBelowPage;
|
||||
|
||||
bool beforeStart = true;
|
||||
bool beforeEnd = true;
|
||||
|
||||
for (SwNodeOffset n(0); n < nodes.Count(); n++)
|
||||
{
|
||||
if (beforeStart && *pPageStart == *nodes[n])
|
||||
{
|
||||
beforeStart = false;
|
||||
}
|
||||
|
||||
if (beforeStart)
|
||||
{
|
||||
pAbovePage.push_front(nodes[n]);
|
||||
}
|
||||
else if (beforeEnd)
|
||||
{
|
||||
pInPage.push_back(nodes[n]);
|
||||
|
||||
if (*pPageEnd == *nodes[n])
|
||||
{
|
||||
beforeEnd = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pBelowPage.push_back(nodes[n]);
|
||||
}
|
||||
}
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 2. Search up from the top of the page
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pAbovePage, rRefMark);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 3. Search down from the bottom of the page
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pBelowPage, rRefMark);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Word has case insensitive styles. LO has case sensitive styles. If we didn't find
|
||||
// it yet, maybe we could with a case insensitive search. Let's do that
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pInPage, rRefMark,
|
||||
false /* bCaseSensitive */);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pAbovePage, rRefMark,
|
||||
false /* bCaseSensitive */);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pBelowPage, rRefMark,
|
||||
false /* bCaseSensitive */);
|
||||
break;
|
||||
}
|
||||
case Reference:
|
||||
case Default:
|
||||
{
|
||||
// Normally, styleref does searches around the field position
|
||||
// For references, styleref acts from the position of the reference not the field
|
||||
// Happily, the previous code saves either one into pReference, so the following is generic for both
|
||||
|
||||
std::deque<SwNode*> pNotBelowElement;
|
||||
std::deque<SwNode*> pBelowElement;
|
||||
|
||||
bool beforeElement = true;
|
||||
|
||||
for (SwNodeOffset n(0); n < nodes.Count(); n++)
|
||||
{
|
||||
if (beforeElement)
|
||||
{
|
||||
pNotBelowElement.push_front(nodes[n]);
|
||||
|
||||
if (*pReference == *nodes[n])
|
||||
{
|
||||
beforeElement = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pBelowElement.push_back(nodes[n]);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Search up until we hit the top of the document
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pNotBelowElement, rRefMark);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// 2. Search down until we hit the bottom of the document
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pBelowElement, rRefMark);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Again, we need to remember that Word styles are not case sensitive
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pNotBelowElement, rRefMark,
|
||||
false /* bCaseSensitive */);
|
||||
if (pTextNd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pTextNd = SearchForStyleAnchor(pSelf, pBelowElement, rRefMark,
|
||||
false /* bCaseSensitive */);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
OSL_FAIL("<SwGetRefFieldType::FindAnchor(..)> - unknown getref element type");
|
||||
}
|
||||
|
||||
if (pTextNd)
|
||||
{
|
||||
*pStt = 0;
|
||||
if (pEnd)
|
||||
*pEnd = pTextNd->GetText().getLength();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return pTextNd;
|
||||
|
||||
@@ -240,7 +240,14 @@ SwExpandPortion *SwTextFormatter::NewFieldPortion( SwTextFormatInfo &rInf,
|
||||
bPlaceHolder = true;
|
||||
break;
|
||||
case SwFieldIds::GetRef:
|
||||
{
|
||||
subType = static_cast<SwGetRefField*>(pField)->GetSubType();
|
||||
if (!bName && subType == REF_STYLE)
|
||||
{
|
||||
static_cast<SwGetRefField*>(pField)->UpdateField(
|
||||
static_txtattr_cast<SwTextField const*>(pHint), pFrame);
|
||||
}
|
||||
|
||||
{
|
||||
OUString const str( bName
|
||||
? pField->GetFieldName()
|
||||
@@ -251,7 +258,8 @@ SwExpandPortion *SwTextFormatter::NewFieldPortion( SwTextFormatInfo &rInf,
|
||||
static_cast<SwFieldPortion*>(pRet)->m_nAttrFieldType = ATTR_BOOKMARKFLD;
|
||||
else if( subType == REF_SETREFATTR )
|
||||
static_cast<SwFieldPortion*>(pRet)->m_nAttrFieldType = ATTR_SETREFATTRFLD;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SwFieldIds::DateTime:
|
||||
subType = static_cast<SwDateTimeField*>(pField)->GetSubType();
|
||||
{
|
||||
|
||||
@@ -642,6 +642,9 @@ public:
|
||||
/// Find the bookmark name.
|
||||
OUString GetBookmarkName( sal_uInt16 nTyp, const OUString* pName, sal_uInt16 nSeqNo );
|
||||
|
||||
/// Find out which style we should use in OOXML
|
||||
OUString GetStyleRefName(const OUString& rName);
|
||||
|
||||
/// Use OutputItem() on an item set according to the parameters.
|
||||
void OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript, bool bExportParentItemSet );
|
||||
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
#include <fmthdft.hxx>
|
||||
#include <authfld.hxx>
|
||||
#include <dbfld.hxx>
|
||||
#include <docsh.hxx>
|
||||
|
||||
#include "sprmids.hxx"
|
||||
|
||||
@@ -1071,6 +1072,18 @@ OUString MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp, const OUString* pNa
|
||||
return BookmarkToWord( sRet ); // #i43956# - encode bookmark accordingly
|
||||
}
|
||||
|
||||
OUString MSWordExportBase::GetStyleRefName(const OUString& rName)
|
||||
{
|
||||
SwTextFormatColls* pTextFormatColls = m_rDoc.GetTextFormatColls();
|
||||
SwTextFormatColl* pTextFormat = pTextFormatColls->FindFormatByName(rName);
|
||||
|
||||
if (pTextFormat == nullptr)
|
||||
return "\"" + rName + "\"";
|
||||
// Didn't find the style, just keep the original name
|
||||
|
||||
return "\"" + m_pStyles->GetStyleWWName(pTextFormat) + "\"";
|
||||
}
|
||||
|
||||
/* File CHRATR.HXX: */
|
||||
void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )
|
||||
{
|
||||
@@ -3319,26 +3332,45 @@ void AttributeOutputBase::TextField( const SwFormatField& rField )
|
||||
sStr = FieldString(eField)
|
||||
+ GetExport().GetBookmarkName(nSubType, nullptr, rRField.GetSeqNo());
|
||||
break;
|
||||
case REF_STYLE:
|
||||
sStr = FieldString(ww::eSTYLEREF)
|
||||
+ GetExport().GetStyleRefName(pField->GetPar1());
|
||||
eField = ww::eSTYLEREF;
|
||||
break;
|
||||
}
|
||||
|
||||
if (eField != ww::eNONE)
|
||||
OUString sExtraFlags = "\\h "; // by default, include a hyperlink
|
||||
|
||||
switch (eField)
|
||||
{
|
||||
switch (pField->GetFormat())
|
||||
{
|
||||
case REF_UPDOWN:
|
||||
sStr += " \\p \\h "; // with hyperlink
|
||||
break;
|
||||
case REF_CHAPTER:
|
||||
sStr += " \\n \\h "; // with hyperlink
|
||||
break;
|
||||
default:
|
||||
sStr += " \\h "; // insert hyperlink
|
||||
break;
|
||||
}
|
||||
GetExport().OutputField(pField, eField, sStr);
|
||||
case ww::eNONE:
|
||||
bWriteExpand = true;
|
||||
break;
|
||||
case ww::eSTYLEREF:
|
||||
sExtraFlags = ""; // styleref fields do not work if they have a hyperlink
|
||||
[[fallthrough]];
|
||||
default:
|
||||
switch (pField->GetFormat())
|
||||
{
|
||||
case REF_NUMBER:
|
||||
sStr += " \\r " + sExtraFlags;
|
||||
break;
|
||||
case REF_NUMBER_FULL_CONTEXT:
|
||||
sStr += " \\w " + sExtraFlags;
|
||||
break;
|
||||
case REF_UPDOWN:
|
||||
sStr += " \\p " + sExtraFlags;
|
||||
break;
|
||||
case REF_NUMBER_NO_CONTEXT:
|
||||
case REF_CHAPTER:
|
||||
sStr += " \\n " + sExtraFlags;
|
||||
break;
|
||||
default:
|
||||
sStr += " " + sExtraFlags;
|
||||
break;
|
||||
}
|
||||
GetExport().OutputField(pField, eField, sStr);
|
||||
}
|
||||
else
|
||||
bWriteExpand = true;
|
||||
}
|
||||
break;
|
||||
case SwFieldIds::CombinedChars:
|
||||
@@ -3388,7 +3420,8 @@ void AttributeOutputBase::TextField( const SwFormatField& rField )
|
||||
break;
|
||||
case SwFieldIds::Chapter:
|
||||
bWriteExpand = true;
|
||||
if (GetExport().m_bOutKF && rField.GetTextField())
|
||||
|
||||
if (rField.GetTextField())
|
||||
{
|
||||
const SwTextNode *pTextNd = GetExport().GetHdFtPageRoot();
|
||||
if (!pTextNd)
|
||||
@@ -3400,10 +3433,22 @@ void AttributeOutputBase::TextField( const SwFormatField& rField )
|
||||
{
|
||||
SwChapterField aCopy(*static_cast<const SwChapterField*>(pField));
|
||||
aCopy.ChangeExpansion(*pTextNd, false);
|
||||
const OUString sStr = FieldString(ww::eSTYLEREF)
|
||||
+ " "
|
||||
+ OUString::number(aCopy.GetLevel() + 1)
|
||||
+ " \\* MERGEFORMAT ";
|
||||
|
||||
OUString sStr;
|
||||
if (GetExport().m_bOutKF) {
|
||||
// In headers and footers, use the chapter number as the style name
|
||||
sStr = FieldString(ww::eSTYLEREF)
|
||||
+ " "
|
||||
+ OUString::number(aCopy.GetLevel() + 1)
|
||||
+ " \\* MERGEFORMAT ";
|
||||
} else {
|
||||
// Otherwise, get the style of the text and use it as the style name
|
||||
const SwTextNode* pOutlineNd = pTextNd->FindOutlineNodeOfLevel(aCopy.GetLevel());
|
||||
|
||||
sStr = FieldString(ww::eSTYLEREF)
|
||||
+ GetExport().GetStyleRefName(pOutlineNd->GetFormatColl()->GetName());
|
||||
}
|
||||
|
||||
GetExport().OutputField(pField, ww::eSTYLEREF, sStr);
|
||||
bWriteExpand = false;
|
||||
}
|
||||
|
||||
@@ -969,8 +969,7 @@ tools::Long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
|
||||
bool bHasHandler = aWW8FieldTab[aF.nId] != nullptr;
|
||||
if (aF.nId == 10) // STYLEREF
|
||||
{
|
||||
// STYLEREF, by default these are not handled.
|
||||
bHasHandler = false;
|
||||
bool bHandledByChapter = false;
|
||||
sal_uInt64 nOldPos = m_pStrm->Tell();
|
||||
OUString aStr;
|
||||
aF.nLCode = m_xSBase->WW8ReadString(*m_pStrm, aStr, m_xPlcxMan->GetCpOfs() + aF.nSCode, aF.nLCode, m_eTextCharSet);
|
||||
@@ -980,9 +979,9 @@ tools::Long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
|
||||
sal_Int32 nRet = aReadParam.SkipToNextToken();
|
||||
if (nRet == -2 && !aReadParam.GetResult().isEmpty())
|
||||
// Single numeric argument: this can be handled by SwChapterField.
|
||||
bHasHandler = rtl::isAsciiDigit(aReadParam.GetResult()[0]);
|
||||
bHandledByChapter = rtl::isAsciiDigit(aReadParam.GetResult()[0]);
|
||||
|
||||
if (bHasHandler)
|
||||
if (bHandledByChapter)
|
||||
{
|
||||
nRet = aReadParam.SkipToNextToken();
|
||||
// Handle using SwChapterField only in case there is no \[a-z]
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
// #i83479#
|
||||
#define REFFLDFLAG_HEADING 0x7100
|
||||
#define REFFLDFLAG_NUMITEM 0x7200
|
||||
#define REFFLDFLAG_STYLE 0xc000
|
||||
/* we skip past 0x8000, 0x9000, 0xa000 and 0xb000 as when we bitwise 'and'
|
||||
with REFFLDFLAG they are false */
|
||||
|
||||
static sal_uInt16 nFieldDlgFormatSel = 0;
|
||||
|
||||
@@ -82,6 +85,7 @@ SwFieldRefPage::SwFieldRefPage(weld::Container* pPage, weld::DialogController* p
|
||||
// #i83479#
|
||||
m_sHeadingText = m_xTypeLB->get_text(3);
|
||||
m_sNumItemText = m_xTypeLB->get_text(4);
|
||||
m_sStyleText = m_xTypeLB->get_text(5);
|
||||
|
||||
auto nHeight = m_xTypeLB->get_height_rows(8);
|
||||
auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH;
|
||||
@@ -239,6 +243,9 @@ void SwFieldRefPage::Reset(const SfxItemSet* )
|
||||
m_xTypeLB->append(OUString::number(REFFLDFLAG_ENDNOTE), m_sEndnoteText);
|
||||
}
|
||||
|
||||
// stylerefs
|
||||
m_xTypeLB->append(OUString::number(REFFLDFLAG_STYLE), m_sStyleText);
|
||||
|
||||
m_xTypeLB->thaw();
|
||||
|
||||
// select old Pos
|
||||
@@ -274,7 +281,7 @@ void SwFieldRefPage::Reset(const SfxItemSet* )
|
||||
}
|
||||
}
|
||||
TypeHdl(*m_xTypeLB);
|
||||
if (nFormatBoxPosition < m_xFormatLB->n_children())
|
||||
if (!IsFieldEdit() && nFormatBoxPosition < m_xFormatLB->n_children())
|
||||
{
|
||||
m_xFormatLB->select(nFormatBoxPosition);
|
||||
}
|
||||
@@ -356,6 +363,17 @@ IMPL_LINK_NOARG(SwFieldRefPage, TypeHdl, weld::TreeView&, void)
|
||||
nFlag = REFFLDFLAG;
|
||||
break;
|
||||
}
|
||||
|
||||
case REF_STYLE:
|
||||
{
|
||||
SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField()));
|
||||
if (pRefField)
|
||||
{
|
||||
sName = pRefField->GetPar1();
|
||||
}
|
||||
nFlag = REFFLDFLAG_STYLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_xTypeLB->find_text(sName) == -1) // reference to deleted mark
|
||||
@@ -610,7 +628,7 @@ void SwFieldRefPage::UpdateSubType(const OUString& filterString)
|
||||
m_xSelectionToolTipLB->append(sId,
|
||||
pIDoc->getOutlineText(nOutlIdx, pSh->GetLayout(), true, true, false));
|
||||
if ((IsFieldEdit() && pRefField
|
||||
&& pRefField->GetReferencedTextNode() == maOutlineNodes[nOutlIdx])
|
||||
&& pRefField->GetReferencedTextNode(nullptr, nullptr) == maOutlineNodes[nOutlIdx])
|
||||
|| mpSavedSelectedTextNode == maOutlineNodes[nOutlIdx])
|
||||
{
|
||||
m_sSelectionToolTipLBId = sId;
|
||||
@@ -645,7 +663,7 @@ void SwFieldRefPage::UpdateSubType(const OUString& filterString)
|
||||
m_xSelectionToolTipLB->append(sId,
|
||||
pIDoc->getListItemText(*maNumItems[nNumItemIdx], *pSh->GetLayout()));
|
||||
if ((IsFieldEdit() && pRefField
|
||||
&& pRefField->GetReferencedTextNode() == maNumItems[nNumItemIdx]->GetTextNode())
|
||||
&& pRefField->GetReferencedTextNode(nullptr, nullptr) == maNumItems[nNumItemIdx]->GetTextNode())
|
||||
|| mpSavedSelectedTextNode == maNumItems[nNumItemIdx]->GetTextNode())
|
||||
{
|
||||
m_sSelectionToolTipLBId = sId;
|
||||
@@ -660,6 +678,32 @@ void SwFieldRefPage::UpdateSubType(const OUString& filterString)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nTypeId == REFFLDFLAG_STYLE)
|
||||
{
|
||||
const IDocumentOutlineNodes* pIDoc(pSh->getIDocumentOutlineNodesAccess());
|
||||
pIDoc->getOutlineNodes(maOutlineNodes);
|
||||
|
||||
SfxStyleSheetBasePool* pStyleSheetPool
|
||||
= pSh->GetDoc()->GetDocShell()->GetStyleSheetPool();
|
||||
auto stylesheetIterator
|
||||
= pStyleSheetPool->CreateIterator(SfxStyleFamily::Para, SfxStyleSearchBits::Used);
|
||||
|
||||
SfxStyleSheetBase* pStyle = stylesheetIterator->First();
|
||||
while (pStyle != nullptr)
|
||||
{
|
||||
bool isSubstring = MatchSubstring(pStyle->GetName(), filterString);
|
||||
|
||||
if (isSubstring)
|
||||
{
|
||||
m_xSelectionLB->append_text(pStyle->GetName());
|
||||
}
|
||||
|
||||
pStyle = stylesheetIterator->Next();
|
||||
}
|
||||
|
||||
if (IsFieldEdit() && pRefField)
|
||||
sOldSel = pRefField->GetPar1();
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the fields to Seq-FieldType:
|
||||
@@ -803,6 +847,7 @@ sal_Int32 SwFieldRefPage::FillFormatLB(sal_uInt16 nTypeId)
|
||||
|
||||
// reference has less that the annotation
|
||||
sal_uInt16 nSize( 0 );
|
||||
sal_uInt16 nOffset( 0 );
|
||||
bool bAddCrossRefFormats( false );
|
||||
switch (nTypeId)
|
||||
{
|
||||
@@ -818,6 +863,11 @@ sal_Int32 SwFieldRefPage::FillFormatLB(sal_uInt16 nTypeId)
|
||||
case REFFLDFLAG_ENDNOTE:
|
||||
nSize = FMT_REF_PAGE_PGDSC_IDX + 1;
|
||||
break;
|
||||
case REFFLDFLAG_STYLE:
|
||||
nOffset = FMT_REF_TEXT_IDX;
|
||||
nSize = FMT_REF_UPDOWN_IDX + 1 - nOffset;
|
||||
bAddCrossRefFormats = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// #i83479#
|
||||
@@ -837,7 +887,7 @@ sal_Int32 SwFieldRefPage::FillFormatLB(sal_uInt16 nTypeId)
|
||||
nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
|
||||
|
||||
SwFieldTypesEnum nFieldType = static_cast<SwFieldTypesEnum>(nTypeId);
|
||||
for (sal_uInt16 i = 0; i < nSize; i++)
|
||||
for (sal_uInt16 i = nOffset; i < nSize + nOffset; i++)
|
||||
{
|
||||
OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i )));
|
||||
m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(nFieldType, i));
|
||||
@@ -1077,6 +1127,18 @@ bool SwFieldRefPage::FillItemSet(SfxItemSet* )
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nTypeId == REFFLDFLAG_STYLE)
|
||||
{
|
||||
int nEntry = m_xSelectionLB->get_selected_index();
|
||||
if (nEntry != -1)
|
||||
{
|
||||
aName = m_xSelectionLB->get_text(nEntry);
|
||||
nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
|
||||
nSubType = REF_STYLE;
|
||||
} else {
|
||||
SAL_WARN("sw.ui", "<SwFieldRefPage::FillItemSet(..)> no entry selected in selection listbox!");
|
||||
}
|
||||
}
|
||||
else // SequenceFields
|
||||
{
|
||||
// get fields for Seq-FieldType:
|
||||
|
||||
@@ -34,6 +34,7 @@ class SwFieldRefPage : public SwFieldPage
|
||||
// #i83479#
|
||||
OUString m_sHeadingText;
|
||||
OUString m_sNumItemText;
|
||||
OUString m_sStyleText;
|
||||
|
||||
IDocumentOutlineNodes::tSortedOutlineNodeList maOutlineNodes;
|
||||
IDocumentListItems::tSortedNodeNumList maNumItems;
|
||||
|
||||
@@ -567,7 +567,7 @@ void SwEditWin::RequestHelp(const HelpEvent &rEvt)
|
||||
if ( pRefField->IsRefToHeadingCrossRefBookmark() ||
|
||||
pRefField->IsRefToNumItemCrossRefBookmark() )
|
||||
{
|
||||
sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout());
|
||||
sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout(), nullptr, nullptr);
|
||||
if ( sText.getLength() > 80 )
|
||||
{
|
||||
sText = OUString::Concat(sText.subView(0, 80)) + "...";
|
||||
|
||||
@@ -66,6 +66,8 @@
|
||||
#include <authfld.hxx>
|
||||
#include <flddat.hxx>
|
||||
#include <fldmgr.hxx>
|
||||
#include <ndtxt.hxx>
|
||||
#include <cntfrm.hxx>
|
||||
#include <flddropdown.hxx>
|
||||
#include <strings.hrc>
|
||||
#include <tox.hxx>
|
||||
@@ -1132,6 +1134,7 @@ bool SwFieldMgr::InsertField(
|
||||
}
|
||||
nFormatId %= SAL_N_ELEMENTS(FMT_REF_ARY);
|
||||
}
|
||||
|
||||
pField.reset(new SwGetRefField(pTyp, rData.m_sPar1, sReferenceLanguage, nSubType, nSeqNo, nFormatId));
|
||||
bExp = true;
|
||||
break;
|
||||
|
||||
@@ -707,7 +707,7 @@ void SwContentType::FillMemberList(bool* pbContentChanged)
|
||||
{
|
||||
OUString sExpandedTextOfReferencedTextNode =
|
||||
pRefField->GetExpandedTextOfReferencedTextNode(
|
||||
*m_pWrtShell->GetLayout());
|
||||
*m_pWrtShell->GetLayout(), nullptr, nullptr);
|
||||
if (sExpandedTextOfReferencedTextNode.getLength() > 80)
|
||||
{
|
||||
sExpandedTextOfReferencedTextNode = OUString::Concat(
|
||||
|
||||
@@ -5829,7 +5829,7 @@ static const FieldConversionMap_t & lcl_GetFieldConversion()
|
||||
{"SEQ", {"SetExpression", FIELD_SEQ }},
|
||||
{"SET", {"SetExpression", FIELD_SET }},
|
||||
// {"SKIPIF", {"", FIELD_SKIPIF }},
|
||||
// {"STYLEREF", {"", FIELD_STYLEREF }},
|
||||
{"STYLEREF", {"GetReference", FIELD_STYLEREF }},
|
||||
{"SUBJECT", {"DocInfo.Subject", FIELD_SUBJECT }},
|
||||
{"SYMBOL", {"", FIELD_SYMBOL }},
|
||||
{"TEMPLATE", {"TemplateName", FIELD_TEMPLATE }},
|
||||
@@ -7519,9 +7519,11 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
break;
|
||||
case FIELD_PAGEREF:
|
||||
case FIELD_REF:
|
||||
case FIELD_STYLEREF:
|
||||
if (xFieldProperties.is() && !IsInTOC())
|
||||
{
|
||||
bool bPageRef = aIt->second.eFieldId == FIELD_PAGEREF;
|
||||
bool bStyleRef = aIt->second.eFieldId == FIELD_STYLEREF;
|
||||
|
||||
// Do we need a GetReference (default) or a GetExpression field?
|
||||
uno::Reference< text::XTextFieldsSupplier > xFieldsSupplier( GetTextDocument(), uno::UNO_QUERY );
|
||||
@@ -7531,12 +7533,50 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
"com.sun.star.text.FieldMaster.SetExpression."
|
||||
+ sFirstParam))
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
|
||||
uno::Any( sal_Int16(text::ReferenceFieldSource::BOOKMARK)) );
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_SOURCE_NAME),
|
||||
uno::Any(sFirstParam) );
|
||||
if (bStyleRef)
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
|
||||
uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
|
||||
|
||||
OUString sStyleSheetName
|
||||
= GetStyleSheetTable()->ConvertStyleName(sFirstParam, true);
|
||||
|
||||
uno::Any aStyleDisplayName;
|
||||
|
||||
uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(
|
||||
GetTextDocument(), uno::UNO_QUERY_THROW);
|
||||
uno::Reference<container::XNameAccess> xStyleFamilies
|
||||
= xStylesSupplier->getStyleFamilies();
|
||||
uno::Reference<container::XNameAccess> xStyles;
|
||||
xStyleFamilies->getByName(getPropertyName(PROP_PARAGRAPH_STYLES))
|
||||
>>= xStyles;
|
||||
uno::Reference<css::beans::XPropertySet> xStyle;
|
||||
|
||||
try
|
||||
{
|
||||
xStyles->getByName(sStyleSheetName) >>= xStyle;
|
||||
aStyleDisplayName = xStyle->getPropertyValue("DisplayName");
|
||||
}
|
||||
catch (css::container::NoSuchElementException)
|
||||
{
|
||||
aStyleDisplayName <<= sStyleSheetName;
|
||||
}
|
||||
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_SOURCE_NAME), aStyleDisplayName);
|
||||
}
|
||||
else
|
||||
{
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
|
||||
uno::Any( sal_Int16(text::ReferenceFieldSource::BOOKMARK)) );
|
||||
|
||||
xFieldProperties->setPropertyValue(
|
||||
getPropertyName(PROP_SOURCE_NAME),
|
||||
uno::Any(sFirstParam));
|
||||
}
|
||||
|
||||
sal_Int16 nFieldPart = (bPageRef ? text::ReferenceFieldPart::PAGE : text::ReferenceFieldPart::TEXT);
|
||||
OUString sValue;
|
||||
if( lcl_FindInCommand( pContext->GetCommand(), 'p', sValue ))
|
||||
@@ -7631,7 +7671,6 @@ void DomainMapper_Impl::CloseFieldCommand()
|
||||
handleFieldSet(pContext, xFieldInterface, xFieldProperties);
|
||||
break;
|
||||
case FIELD_SKIPIF : break;
|
||||
case FIELD_STYLEREF : break;
|
||||
case FIELD_SUBJECT :
|
||||
{
|
||||
if (!sFirstParam.isEmpty())
|
||||
|
||||
@@ -209,8 +209,9 @@ enum FieldId
|
||||
*/
|
||||
,FIELD_SKIPIF
|
||||
/* STYLEREF stylename \* MERGEFORMAT ->
|
||||
not imported in old ww8 filter
|
||||
todo: add an equivalent field type
|
||||
implemented using GetReference, but some switches are not implemented yet
|
||||
\l isn't implemented
|
||||
\t isn't implemented
|
||||
*/
|
||||
,FIELD_STYLEREF
|
||||
/* SUBJECT subject \* Defaultswitch \* MERGEFORMAT ->
|
||||
|
||||
@@ -119,6 +119,7 @@ enum FieldIdEnum {
|
||||
FIELD_ID_REF_BOOKMARK, // get reference field (bookmark)
|
||||
FIELD_ID_REF_FOOTNOTE, // get reference field (footnote)
|
||||
FIELD_ID_REF_ENDNOTE, // get reference field (endnote)
|
||||
FIELD_ID_REF_STYLE, // styleref field
|
||||
FIELD_ID_DDE, // DDE field
|
||||
|
||||
FIELD_ID_BIBLIOGRAPHY, // bibliography index entry
|
||||
|
||||
@@ -1915,6 +1915,7 @@ namespace xmloff::token {
|
||||
TOKEN( "structure-protected", XML_STRUCTURE_PROTECTED ),
|
||||
TOKEN( "style", XML_STYLE ),
|
||||
TOKEN( "style-name", XML_STYLE_NAME ),
|
||||
TOKEN( "style-ref", XML_STYLE_REF ),
|
||||
TOKEN( "styles", XML_STYLES ),
|
||||
TOKEN( "stylesheet", XML_STYLESHEET ),
|
||||
TOKEN( "sub-table", XML_SUB_TABLE ),
|
||||
|
||||
@@ -563,6 +563,9 @@ enum FieldIdEnum XMLTextFieldExport::MapFieldName(
|
||||
case ReferenceFieldSource::ENDNOTE:
|
||||
nToken = FIELD_ID_REF_ENDNOTE;
|
||||
break;
|
||||
case ReferenceFieldSource::STYLE:
|
||||
nToken = FIELD_ID_REF_STYLE;
|
||||
break;
|
||||
default:
|
||||
nToken = FIELD_ID_UNKNOWN;
|
||||
break;
|
||||
@@ -703,6 +706,7 @@ bool XMLTextFieldExport::IsStringField(
|
||||
case FIELD_ID_REF_BOOKMARK:
|
||||
case FIELD_ID_REF_FOOTNOTE:
|
||||
case FIELD_ID_REF_ENDNOTE:
|
||||
case FIELD_ID_REF_STYLE:
|
||||
case FIELD_ID_MACRO:
|
||||
case FIELD_ID_TEMPLATE_NAME:
|
||||
case FIELD_ID_CHAPTER:
|
||||
@@ -914,6 +918,7 @@ void XMLTextFieldExport::ExportFieldAutoStyle(
|
||||
case FIELD_ID_REF_BOOKMARK:
|
||||
case FIELD_ID_REF_FOOTNOTE:
|
||||
case FIELD_ID_REF_ENDNOTE:
|
||||
case FIELD_ID_REF_STYLE:
|
||||
case FIELD_ID_MACRO:
|
||||
case FIELD_ID_REFPAGE_SET:
|
||||
case FIELD_ID_REFPAGE_GET:
|
||||
@@ -1646,6 +1651,30 @@ void XMLTextFieldExport::ExportFieldHelper(
|
||||
sPresentation);
|
||||
break;
|
||||
|
||||
case FIELD_ID_REF_STYLE:
|
||||
{
|
||||
ProcessString(XML_REFERENCE_FORMAT,
|
||||
MapReferenceType(GetInt16Property(gsPropertyReferenceFieldPart, rPropSet)),
|
||||
XML_TEMPLATE);
|
||||
ProcessString(XML_REF_NAME, GetStringProperty(gsPropertySourceName, rPropSet));
|
||||
if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage)
|
||||
&& GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
|
||||
{
|
||||
// export text:reference-language attribute, if not empty
|
||||
ProcessString(XML_REFERENCE_LANGUAGE,
|
||||
GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true,
|
||||
XML_NAMESPACE_LO_EXT);
|
||||
}
|
||||
SvXMLElementExport aElem(
|
||||
GetExport(),
|
||||
XML_NAMESPACE_LO_EXT,
|
||||
MapReferenceSource(GetInt16Property(gsPropertyReferenceFieldSource, rPropSet)),
|
||||
false,
|
||||
false);
|
||||
GetExport().Characters(sPresentation);
|
||||
break;
|
||||
}
|
||||
|
||||
case FIELD_ID_DDE:
|
||||
// name from field master
|
||||
ProcessString(XML_CONNECTION_NAME,
|
||||
@@ -3160,6 +3189,9 @@ enum XMLTokenEnum XMLTextFieldExport::MapReferenceSource(sal_Int16 nType)
|
||||
case ReferenceFieldSource::ENDNOTE:
|
||||
eElement = XML_NOTE_REF;
|
||||
break;
|
||||
case ReferenceFieldSource::STYLE:
|
||||
eElement = XML_STYLE_REF;
|
||||
break;
|
||||
default:
|
||||
OSL_FAIL("unknown reference source");
|
||||
break;
|
||||
|
||||
@@ -407,6 +407,7 @@ XMLTextFieldImportContext::CreateTextFieldImportContext(
|
||||
case XML_ELEMENT(TEXT, XML_BOOKMARK_REF):
|
||||
case XML_ELEMENT(TEXT, XML_NOTE_REF):
|
||||
case XML_ELEMENT(TEXT, XML_SEQUENCE_REF):
|
||||
case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
|
||||
pContext = new XMLReferenceFieldImportContext( rImport, rHlp, nToken );
|
||||
break;
|
||||
|
||||
@@ -2509,6 +2510,9 @@ void XMLReferenceFieldImportContext::startFastElement(
|
||||
case XML_ELEMENT(TEXT, XML_SEQUENCE_REF):
|
||||
nSource = ReferenceFieldSource::SEQUENCE_FIELD;
|
||||
break;
|
||||
case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
|
||||
nSource = ReferenceFieldSource::STYLE;
|
||||
break;
|
||||
default:
|
||||
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
|
||||
bTypeOK = false;
|
||||
@@ -2577,6 +2581,7 @@ void XMLReferenceFieldImportContext::PrepareField(
|
||||
{
|
||||
case XML_ELEMENT(TEXT, XML_REFERENCE_REF):
|
||||
case XML_ELEMENT(TEXT, XML_BOOKMARK_REF):
|
||||
case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
|
||||
xPropertySet->setPropertyValue("SourceName", Any(sName));
|
||||
break;
|
||||
|
||||
|
||||
@@ -1815,6 +1815,7 @@ stroke-width
|
||||
structure-protected
|
||||
style
|
||||
style-name
|
||||
style-ref
|
||||
styles
|
||||
stylesheet
|
||||
sub-table
|
||||
|
||||
Reference in New Issue
Block a user