From 8c632d8a837cc722c6e7b3b400f6d97edf9f9800 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 5 Apr 2022 10:53:22 +0200 Subject: sw content controls: add initial layout support - portions inside content controls are not text portions but content control portions - teach SwTextPaintInfo::DrawViewOpt() to paint field shadings for content control portions - teach the attribute stack code about RES_TXTATR_CONTENTCONTROL, so if the whole document is just a content control, then adding text before/after the content control is properly text portions, not content control portions Change-Id: Ia9f955a5f7c7a4fd633899fafa8fc723e7c0d050 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132556 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- sw/qa/core/unocore/unocore.cxx | 12 ++++++++++++ sw/source/core/inc/swfont.hxx | 3 +++ sw/source/core/inc/txttypes.hxx | 1 + sw/source/core/text/atrhndl.hxx | 2 +- sw/source/core/text/atrstck.cxx | 15 +++++++++++++++ sw/source/core/text/inftxt.cxx | 1 + sw/source/core/text/itratr.cxx | 2 ++ sw/source/core/text/itrform2.cxx | 20 ++++++++++++++++++++ sw/source/core/text/xmldump.cxx | 2 ++ sw/source/core/txtnode/swfont.cxx | 3 +++ 10 files changed, 60 insertions(+), 1 deletion(-) (limited to 'sw') diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index c9bca82ae2f8..19ad5d5fd48b 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -404,6 +404,18 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlTextPortionEnum) uno::Reference xContentEnum = xContentEnumAccess->createEnumeration(); uno::Reference xContent(xContentEnum->nextElement(), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("test"), xContent->getString()); + + // Also test the generated layout: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwFieldPortion", "expand", ""); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: PortionType::ContentControl + // - Actual : PortionType::Text + // i.e. SwContentControl generated a plain text portion, not a dedicated content control + // portion. + assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", "type", + "PortionType::ContentControl"); + assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", "portion", "test"); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx index a2eedaca5f64..40a4c2e8d66c 100644 --- a/sw/source/core/inc/swfont.hxx +++ b/sw/source/core/inc/swfont.hxx @@ -158,6 +158,7 @@ class SwFont sal_uInt8 m_nToxCount; // counts the nesting depth of the Tox sal_uInt8 m_nRefCount; // counts the nesting depth of the Refs sal_uInt8 m_nMetaCount; // count META/METAFIELD + sal_uInt8 m_nContentControlCount; // count CONTENTCONTROL sal_uInt8 m_nInputFieldCount; // count INPUTFIELD SwFontScript m_nActual; // actual font (Latin, CJK or CTL) @@ -250,6 +251,8 @@ public: bool IsRef() const { return ( 0 != m_nRefCount ); } sal_uInt8 &GetMeta() { return m_nMetaCount; } bool IsMeta() const { return (0 != m_nMetaCount); } + sal_uInt8& GetContentControl() { return m_nContentControlCount; } + bool IsContentControl() const { return m_nContentControlCount != 0; } sal_uInt8 &GetInputField() { return m_nInputFieldCount; } bool IsInputField() const { return (0 != m_nInputFieldCount); } inline void SetGreyWave( const bool bNew ); diff --git a/sw/source/core/inc/txttypes.hxx b/sw/source/core/inc/txttypes.hxx index e65ed26dc128..d876b0f8e037 100644 --- a/sw/source/core/inc/txttypes.hxx +++ b/sw/source/core/inc/txttypes.hxx @@ -49,6 +49,7 @@ enum class PortionType Ref = 0x808b, IsoRef = 0x808c, Meta = 0x808d, + ContentControl = 0x808e, Expand = 0xc080, Blank = 0xc081, diff --git a/sw/source/core/text/atrhndl.hxx b/sw/source/core/text/atrhndl.hxx index 8bb7845f2760..851615325a06 100644 --- a/sw/source/core/text/atrhndl.hxx +++ b/sw/source/core/text/atrhndl.hxx @@ -18,7 +18,7 @@ */ #pragma once -#define NUM_ATTRIBUTE_STACKS 44 +#define NUM_ATTRIBUTE_STACKS 45 #include #include diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx index f5cb36cb03f6..7fab6da10c5e 100644 --- a/sw/source/core/text/atrstck.cxx +++ b/sw/source/core/text/atrstck.cxx @@ -123,6 +123,7 @@ const sal_uInt8 StackPos[ RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN + 1 ] = 42, // RES_TXTATR_CJK_RUBY, // 53 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 54 43, // RES_TXTATR_INPUTFIELD // 55 + 44, // RES_TXTATR_CONTENTCONTROL // 56 }; namespace CharFormat @@ -516,6 +517,10 @@ void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr ) { rFnt.GetMeta()--; } + else if (nAttr == RES_TXTATR_CONTENTCONTROL) + { + rFnt.GetContentControl()--; + } else if ( RES_TXTATR_CJK_RUBY == nAttr ) { // ruby stack has no more attributes @@ -810,6 +815,16 @@ void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, bool bPush ) else rFnt.GetMeta()--; break; + case RES_TXTATR_CONTENTCONTROL: + if (bPush) + { + rFnt.GetContentControl()++; + } + else + { + rFnt.GetContentControl()--; + } + break; case RES_TXTATR_INPUTFIELD : if ( bPush ) rFnt.GetInputField()++; diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx index 32219500921a..5f4cbb95b6fc 100644 --- a/sw/source/core/text/inftxt.cxx +++ b/sw/source/core/text/inftxt.cxx @@ -1318,6 +1318,7 @@ void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor, case PortionType::Tox: case PortionType::Ref: case PortionType::Meta: + case PortionType::ContentControl: case PortionType::ControlChar: if ( !GetOpt().IsPagePreview() && !GetOpt().IsReadonly() diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index 95f7929a0e14..4f4a840a564f 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -510,6 +510,7 @@ static bool CanSkipOverRedline( case RES_TXTATR_INETFMT: case RES_TXTATR_CJK_RUBY: case RES_TXTATR_INPUTFIELD: + case RES_TXTATR_CONTENTCONTROL: { if (!isTheAnswerYes) return false; // always break } @@ -600,6 +601,7 @@ static bool CanSkipOverRedline( case RES_TXTATR_INETFMT: case RES_TXTATR_CJK_RUBY: case RES_TXTATR_INPUTFIELD: + case RES_TXTATR_CONTENTCONTROL: { if (!isTheAnswerYes) return false; } diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 2f978289a267..f9e6f45a4433 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -863,6 +863,13 @@ public: void SetShadowColor(const Color& rCol ) { m_aShadowColor = rCol; } }; +/// A content control portion is a text portion that is inside RES_TXTATR_CONTENTCONTROL. +class SwContentControlPortion : public SwTextPortion +{ +public: + SwContentControlPortion() { SetWhichPor(PortionType::ContentControl); } + virtual void Paint(const SwTextPaintInfo& rInf) const override; +}; } void SwMetaPortion::Paint( const SwTextPaintInfo &rInf ) const @@ -879,6 +886,15 @@ void SwMetaPortion::Paint( const SwTextPaintInfo &rInf ) const } } +void SwContentControlPortion::Paint(const SwTextPaintInfo& rInf) const +{ + if (Width()) + { + rInf.DrawViewOpt(*this, PortionType::ContentControl); + SwTextPortion::Paint(rInf); + } +} + namespace sw::mark { OUString ExpandFieldmark(IFieldmark* pBM) { @@ -995,6 +1011,10 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const } pPor = pMetaPor; } + else if (GetFnt()->IsContentControl()) + { + pPor = new SwContentControlPortion; + } else { // Only at the End! diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx index 13215bca13c9..fb45c0920f17 100644 --- a/sw/source/core/text/xmldump.cxx +++ b/sw/source/core/text/xmldump.cxx @@ -79,6 +79,8 @@ const char* sw::PortionTypeToString(PortionType nType) return "PortionType::IsoRef"; case PortionType::Meta: return "PortionType::Meta"; + case PortionType::ContentControl: + return "PortionType::ContentControl"; case PortionType::FieldMark: return "PortionType::FieldMark"; case PortionType::FieldFormCheckbox: diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx index 67028f766761..eb08f33696cc 100644 --- a/sw/source/core/txtnode/swfont.cxx +++ b/sw/source/core/txtnode/swfont.cxx @@ -662,6 +662,7 @@ SwFont::SwFont( const SwFont &rFont ) m_nToxCount = 0; m_nRefCount = 0; m_nMetaCount = 0; + m_nContentControlCount = 0; m_nInputFieldCount = 0; m_bFontChg = rFont.m_bFontChg; m_bOrgChg = rFont.m_bOrgChg; @@ -677,6 +678,7 @@ SwFont::SwFont( const SwAttrSet* pAttrSet, m_nToxCount = 0; m_nRefCount = 0; m_nMetaCount = 0; + m_nContentControlCount = 0; m_nInputFieldCount = 0; m_bPaintBlank = false; m_bGreyWave = false; @@ -849,6 +851,7 @@ SwFont& SwFont::operator=( const SwFont &rFont ) m_nToxCount = 0; m_nRefCount = 0; m_nMetaCount = 0; + m_nContentControlCount = 0; m_nInputFieldCount = 0; m_bFontChg = rFont.m_bFontChg; m_bOrgChg = rFont.m_bOrgChg; -- cgit