officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu |   13 ++
 sw/inc/cmdid.h                                                      |    1 
 sw/inc/formatcontentcontrol.hxx                                     |    6 +
 sw/qa/uibase/wrtsh/wrtsh.cxx                                        |   23 +++-
 sw/sdi/_textsh.sdi                                                  |    6 +
 sw/sdi/swriter.sdi                                                  |   17 ++
 sw/source/uibase/inc/wrtsh.hxx                                      |    3 
 sw/source/uibase/shells/textsh.cxx                                  |    8 +
 sw/source/uibase/uiview/view.cxx                                    |    2 
 sw/source/uibase/wrtsh/wrtsh1.cxx                                   |   31 
++++-
 sw/uiconfig/swriter/menubar/menubar.xml                             |    7 +
 writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx                  |   46 
++++++++
 writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx     |binary
 writerfilter/source/dmapper/DomainMapper.cxx                        |   57 
+++++++++-
 writerfilter/source/dmapper/DomainMapper_Impl.cxx                   |   21 +++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx                   |    4 
 writerfilter/source/dmapper/SdtHelper.cxx                           |   18 +++
 writerfilter/source/dmapper/SdtHelper.hxx                           |   23 +++-
 writerfilter/source/dmapper/TextEffectsHandler.cxx                  |    1 
 writerfilter/source/dmapper/TextEffectsHandler.hxx                  |    8 -
 writerfilter/source/ooxml/model.xml                                 |    7 -
 21 files changed, 278 insertions(+), 24 deletions(-)

New commits:
commit 018776f52ffa14a579b0ea752a2b59de1a62b4e4
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon May 2 08:43:19 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue May 3 13:29:26 2022 +0200

    sw content controls, checkbox: add insert UI
    
    - extend SwWrtShell::InsertContentControl() to be able to create
      multiple content control types
    
    - a new checkbox content control's content is always a non-checked
      checkbox
    
    - expose this as a new .uno:InsertCheckboxContentControl uno command
    
    - add this new command to the bottom of the form menu -- now that we
      have two types of content controls, have that in a sub-menu
    
    (cherry picked from commit 02a5bd2e6c4eee50cbd8cb4ed009731c409711a5)
    
    Change-Id: I058659600b3face69b89262feb0979fff32521c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133744
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git 
a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index 86c6302f6e18..b15b1ebb6a30 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -614,6 +614,11 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:ContentControlsMenu" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Content Controls</value>
+        </prop>
+      </node>
       <node oor:name=".uno:InsertContentControl" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Insert Rich Text Content Control</value>
@@ -622,6 +627,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:InsertCheckboxContentControl" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Insert Check Box Content Control</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:InsertObjectDialog" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Insert Other Objects</value>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 8499a54b2b28..6f3673b62811 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -211,6 +211,7 @@
 #define FN_INSERT_LINEBREAK     (FN_INSERT + 18)    /* Newline */
 #define FN_INSERT_FIELD_DATA_ONLY (FN_INSERT + 19)  /* Field dialog for mail 
merge*/
 #define FN_INSERT_CONTENT_CONTROL (FN_INSERT + 20)  /* Content control */
+#define FN_INSERT_CHECKBOX_CONTENT_CONTROL (FN_INSERT + 21)  /* Checkbox 
content control */
 #define FN_INSERT_OBJECT_DLG    (FN_INSERT + 22)    /* Object */
 #define FN_INSERT_PAGEBREAK     (FN_INSERT + 23)    /* Page break*/
 #define FN_POSTIT               (FN_INSERT + 29)    /* Insert/edit PostIt */
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 54804612a2b5..43309f49f55c 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -31,6 +31,12 @@ class SwTextContentControl;
 class SwTextNode;
 class SwXContentControl;
 
+enum class SwContentControlType
+{
+    RICH_TEXT,
+    CHECKBOX,
+};
+
 /// SfxPoolItem subclass that wraps an SwContentControl.
 class SwFormatContentControl final : public SfxPoolItem
 {
diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx
index b4d4cca09df6..5fddff1d884f 100644
--- a/sw/qa/uibase/wrtsh/wrtsh.cxx
+++ b/sw/qa/uibase/wrtsh/wrtsh.cxx
@@ -136,7 +136,7 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl)
 
     // When inserting a content control:
     SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
-    pWrtShell->InsertContentControl();
+    pWrtShell->InsertContentControl(SwContentControlType::RICH_TEXT);
 
     // Then make sure that the matching text attribute is added to the 
document model:
     SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode();
@@ -144,6 +144,27 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl)
     // InsertContentControl().
     CPPUNIT_ASSERT(pTextNode->GetTextAttrForCharAt(0, 
RES_TXTATR_CONTENTCONTROL));
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testInsertCheckboxContentControl)
+{
+    // Given an empty document:
+    SwDoc* pDoc = createSwDoc();
+
+    // When inserting a content control:
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->InsertContentControl(SwContentControlType::CHECKBOX);
+
+    // Then make sure that the matching text attribute is added to the 
document model:
+    SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode();
+    SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, 
RES_TXTATR_CONTENTCONTROL);
+    auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
+    auto& rFormatContentControl
+        = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
+    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    // Without the accompanying fix in place, this test would have failed, the 
inserted content
+    // control wasn't a checkbox one.
+    CPPUNIT_ASSERT(pContentControl->GetCheckbox());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi
index f1689474467f..8c76493bf36b 100644
--- a/sw/sdi/_textsh.sdi
+++ b/sw/sdi/_textsh.sdi
@@ -278,6 +278,12 @@ interface BaseText
         StateMethod = NoState ;
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
+    FN_INSERT_CHECKBOX_CONTENT_CONTROL  // status(final|play)
+    [
+        ExecMethod = ExecInsert ;
+        StateMethod = NoState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
     FN_INSERT_COLUMN_BREAK // status(final|play)
     [
         ExecMethod = ExecInsert ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 16922267cf85..93d16693c296 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -3049,6 +3049,23 @@ SfxVoidItem InsertContentControl 
FN_INSERT_CONTENT_CONTROL
     GroupId = SfxGroupId::Insert;
 ]
 
+SfxVoidItem InsertCheckboxContentControl FN_INSERT_CHECKBOX_CONTENT_CONTROL
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Insert;
+]
+
 SfxVoidItem InsertMultiIndex FN_INSERT_MULTI_TOX
 ()
 [
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
index 37d82557ac03..a80f42c8315a 100644
--- a/sw/source/uibase/inc/wrtsh.hxx
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -55,6 +55,7 @@ class SwFieldMgr;
 class SfxRequest;
 enum class SwLineBreakClear;
 class SwContentControl;
+enum class SwContentControlType;
 
 namespace i18nutil {
     struct SearchOptions2;
@@ -316,7 +317,7 @@ typedef bool (SwWrtShell::*FNSimpleMove)();
     void    InsertPageBreak(const OUString *pPageDesc = nullptr, const 
::std::optional<sal_uInt16>& rPgNum = std::nullopt);
     void InsertLineBreak(std::optional<SwLineBreakClear> oClear = 
std::nullopt);
     void    InsertColumnBreak();
-    void InsertContentControl();
+    void InsertContentControl(SwContentControlType eType);
     void    InsertFootnote(const OUString &, bool bEndNote = false, bool bEdit 
= true );
     void    SplitNode( bool bAutoFormat = false );
     bool    CanInsert();
diff --git a/sw/source/uibase/shells/textsh.cxx 
b/sw/source/uibase/shells/textsh.cxx
index 7fec748ba488..e8b05efb83b2 100644
--- a/sw/source/uibase/shells/textsh.cxx
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -91,6 +91,7 @@ using namespace ::com::sun::star;
 #include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
 #include <IDocumentUndoRedo.hxx>
+#include <formatcontentcontrol.hxx>
 
 SFX_IMPL_INTERFACE(SwTextShell, SwBaseShell)
 
@@ -219,7 +220,12 @@ void SwTextShell::ExecInsert(SfxRequest &rReq)
         break;
 
     case FN_INSERT_CONTENT_CONTROL:
-        rSh.InsertContentControl();
+        rSh.InsertContentControl(SwContentControlType::RICH_TEXT);
+        rReq.Done();
+        break;
+
+    case FN_INSERT_CHECKBOX_CONTENT_CONTROL:
+        rSh.InsertContentControl(SwContentControlType::CHECKBOX);
         rReq.Done();
         break;
 
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index b43ff17782fc..2fe2ad061456 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -594,7 +594,7 @@ void SwView::CheckReadonlyState()
             SID_CHARMAP,                SID_EMOJI_CONTROL,          
FN_INSERT_SOFT_HYPHEN,
             FN_INSERT_HARDHYPHEN,       FN_INSERT_HARD_SPACE,       
FN_INSERT_NNBSP,
             FN_INSERT_BREAK,            FN_INSERT_LINEBREAK,        
FN_INSERT_COLUMN_BREAK,
-            FN_INSERT_BREAK_DLG,        FN_INSERT_CONTENT_CONTROL,
+            FN_INSERT_BREAK_DLG,        FN_INSERT_CONTENT_CONTROL,  
FN_INSERT_CHECKBOX_CONTENT_CONTROL,
             FN_DELETE_SENT,             FN_DELETE_BACK_SENT,        
FN_DELETE_WORD,
             FN_DELETE_BACK_WORD,        FN_DELETE_LINE,             
FN_DELETE_BACK_LINE,
             FN_DELETE_PARA,             FN_DELETE_BACK_PARA,        
FN_DELETE_WHOLE_LINE,
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx 
b/sw/source/uibase/wrtsh/wrtsh1.cxx
index 1d93f1e31983..78e18197f39b 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -1007,7 +1007,7 @@ void SwWrtShell::InsertColumnBreak()
     EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
 }
 
-void SwWrtShell::InsertContentControl()
+void SwWrtShell::InsertContentControl(SwContentControlType eType)
 {
     if (!lcl_IsAllowed(this))
     {
@@ -1021,13 +1021,32 @@ void SwWrtShell::InsertContentControl()
     }
 
     auto pContentControl = std::make_shared<SwContentControl>(nullptr);
-    pContentControl->SetShowingPlaceHolder(true);
-    if (!HasSelection())
+    OUString aPlaceholder;
+    switch (eType)
     {
-        OUString aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
-        Insert(aPlaceholder);
-        Left(CRSR_SKIP_CHARS, /*bSelect=*/true, aPlaceholder.getLength(), 
/*bBasicCall=*/false);
+        case SwContentControlType::RICH_TEXT:
+        {
+            pContentControl->SetShowingPlaceHolder(true);
+            if (!HasSelection())
+            {
+                aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
+            }
+            break;
+        }
+        case SwContentControlType::CHECKBOX:
+        {
+            pContentControl->SetCheckbox(true);
+            // Ballot Box with X
+            pContentControl->SetCheckedState(u"\u2612");
+            // Ballot Box
+            pContentControl->SetUncheckedState(OUString(u"\u2610"));
+            aPlaceholder = u"\u2610";
+            break;
+        }
     }
+    Insert(aPlaceholder);
+    Left(CRSR_SKIP_CHARS, /*bSelect=*/true, aPlaceholder.getLength(),
+            /*bBasicCall=*/false);
     SwFormatContentControl aContentControl(pContentControl, 
RES_TXTATR_CONTENTCONTROL);
     SetAttrItem(aContentControl);
 }
diff --git a/sw/uiconfig/swriter/menubar/menubar.xml 
b/sw/uiconfig/swriter/menubar/menubar.xml
index 526cbac6a8ca..e40052d1384a 100644
--- a/sw/uiconfig/swriter/menubar/menubar.xml
+++ b/sw/uiconfig/swriter/menubar/menubar.xml
@@ -710,7 +710,12 @@
       <menu:menuitem menu:id=".uno:OpenReadOnly"/>
       <menu:menuitem menu:id=".uno:AutoControlFocus"/>
       <menu:menuseparator/>
-      <menu:menuitem menu:id=".uno:InsertContentControl"/>
+      <menu:menu menu:id=".uno:ContentControlsMenu">
+        <menu:menupopup>
+          <menu:menuitem menu:id=".uno:InsertContentControl"/>
+          <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/>
+        </menu:menupopup>
+      </menu:menu>
     </menu:menupopup>
   </menu:menu>
   <menu:menu menu:id=".uno:ToolsMenu">
commit 55e63a2b953be99ceb742407263be92eb3a54df4
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Apr 29 08:12:25 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue May 3 13:29:08 2022 +0200

    sw content controls, checkbox: add DOCX import
    
    My expectation was that <w14:checked w14:val="0"/> would be mapped to a
    single SPRM where the int value is 0 or 1 depending on if this is a true
    or false boolean. But the w14 tokenizer rules actually created a
    NS_ooxml::LN_CT_SdtCheckbox_checked token with a
    NS_ooxml::LN_CT_OnOff_val token in it, which itself again didn't contain
    just a bool but dedicated NS_ooxml::LN_ST_OnOff_true,
    NS_ooxml::LN_ST_OnOff_1, etc values.
    
    To make this more complicated, TextEffectsHandler even depends on this
    weird behavior.
    
    Bring the w14 rules closer to the "main" wml rules by folding the
    NS_ooxml::LN_CT_OnOff_val token into the parent token
    (NS_ooxml::LN_CT_SdtCheckbox_checked in this case), but leave the
    NS_ooxml::LN_ST_OnOff_* values unchanged for now.
    
    The rest of the changes are more straightforward: we now handle
    inline/run checkbox SDTs similar to rich text ones, i.e. map them to
    Writer content controls, rather than just doing a poor mapping to
    grab-bags.
    
    The main benefit here is that the checkbox type of Writer content
    controls actually change their value on mouse click, so it's possible to
    fill in such forms.
    
    (cherry picked from commit c53d3a1f4b8430507d54f5fac336870df7a700af)
    
    Conflicts:
            writerfilter/source/dmapper/SdtHelper.hxx
    
    Change-Id: Idbf49a8ff1843d5271f2836e5299c4387bb58e55
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133743
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx 
b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
index da2663b93409..c96cb604f91f 100644
--- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
@@ -84,6 +84,52 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText)
     xContent->getPropertyValue("CharHeight") >>= fCharheight;
     CPPUNIT_ASSERT_EQUAL(24.f, fCharheight);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSdtRunCheckbox)
+{
+    // Given a document with a checkbox inline/run SDT:
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"sdt-run-checkbox.docx";
+
+    // When loading the document:
+    getComponent() = loadFromDesktop(aURL);
+
+    // Then make sure that the doc model has a clickable checkbox content 
control:
+    uno::Reference<text::XTextDocument> xTextDocument(getComponent(), 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> 
xParaEnumAccess(xTextDocument->getText(),
+                                                                  
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = 
xParaEnumAccess->createEnumeration();
+    uno::Reference<container::XEnumerationAccess> 
xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xPortionEnum = 
xPara->createEnumeration();
+    uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), 
uno::UNO_QUERY);
+    OUString aTextPortionType;
+    xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType;
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: ContentControl
+    // - Actual  : Text
+    // i.e. the SDT was imported as plain text, making it hard to fill in 
checkboxes.
+    CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType);
+    uno::Reference<text::XTextContent> xContentControl;
+    xPortion->getPropertyValue("ContentControl") >>= xContentControl;
+    uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
+    bool bCheckbox{};
+    xContentControlProps->getPropertyValue("Checkbox") >>= bCheckbox;
+    CPPUNIT_ASSERT(bCheckbox);
+    bool bChecked{};
+    xContentControlProps->getPropertyValue("Checked") >>= bChecked;
+    CPPUNIT_ASSERT(bChecked);
+    OUString aCheckedState;
+    xContentControlProps->getPropertyValue("CheckedState") >>= aCheckedState;
+    CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), aCheckedState);
+    OUString aUncheckedState;
+    xContentControlProps->getPropertyValue("UncheckedState") >>= 
aUncheckedState;
+    CPPUNIT_ASSERT_EQUAL(OUString(u"☐"), aUncheckedState);
+    uno::Reference<text::XTextRange> xContentControlRange(xContentControl, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xContentControlRange->getText();
+    uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xContentEnum = 
xContentEnumAccess->createEnumeration();
+    uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), xContent->getString());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx 
b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx
new file mode 100644
index 000000000000..c6718b97c2a0
Binary files /dev/null and 
b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 59215a9d6aa5..2bd6ece56ad4 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1083,6 +1083,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
                 {
                     
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::richText);
                     m_pImpl->PushSdt();
+                    break;
                 }
             }
             m_pImpl->SetSdt(true);
@@ -1094,6 +1095,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
                 switch (m_pImpl->m_pSdtHelper->getControlType())
                 {
                     case SdtControlType::richText:
+                    case SdtControlType::checkBox:
                         m_pImpl->PopSdt();
                         break;
                     default:
@@ -2771,6 +2773,20 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     case NS_ooxml::LN_CT_SdtPlaceholder_docPart:
     case NS_ooxml::LN_CT_SdtPr_color:
     {
+        if (!m_pImpl->GetSdtStarts().empty())
+        {
+            if (nSprmId == NS_ooxml::LN_CT_SdtPr_checkbox)
+            {
+                
m_pImpl->m_pSdtHelper->setControlType(SdtControlType::checkBox);
+                writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+                if (pProperties)
+                {
+                    pProperties->resolve(*this);
+                }
+                break;
+            }
+        }
+
         // this is an unsupported SDT property, create a grab bag for it
         OUString sName;
         switch (nSprmId)
@@ -2819,13 +2835,42 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     }
     break;
     case NS_ooxml::LN_CT_SdtCheckbox_checked:
-        m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtCheckbox_checked", sStringValue);
+        if (!m_pImpl->GetSdtStarts().empty())
+        {
+            // nIntValue is not just 0 or 1, because we're in the w14 
namespace's ST_OnOff.
+            if (nIntValue == NS_ooxml::LN_ST_OnOff_true || nIntValue == 
NS_ooxml::LN_ST_OnOff_1)
+            {
+                m_pImpl->m_pSdtHelper->SetChecked();
+            }
+        }
+        else
+        {
+            m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtCheckbox_checked",
+                                   
TextEffectsHandler::getOnOffString(nIntValue));
+        }
         break;
     case NS_ooxml::LN_CT_SdtCheckbox_checkedState:
-        m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtCheckbox_checkedState", sStringValue);
+        if (!m_pImpl->GetSdtStarts().empty())
+        {
+            
m_pImpl->m_pSdtHelper->SetCheckedState(OUString(sal_Unicode(sStringValue.toInt32(16))));
+        }
+        else
+        {
+            m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtCheckbox_checkedState",
+                                   sStringValue);
+        }
         break;
     case NS_ooxml::LN_CT_SdtCheckbox_uncheckedState:
-        m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtCheckbox_uncheckedState", sStringValue);
+        if (!m_pImpl->GetSdtStarts().empty())
+        {
+            m_pImpl->m_pSdtHelper->SetUncheckedState(
+                OUString(sal_Unicode(sStringValue.toInt32(16))));
+        }
+        else
+        {
+            m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag,
+                                   "ooxml:CT_SdtCheckbox_uncheckedState", 
sStringValue);
+        }
         break;
     case NS_ooxml::LN_CT_SdtDocPart_docPartGallery:
         m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, 
"ooxml:CT_SdtDocPart_docPartGallery", sStringValue);
@@ -2931,6 +2976,12 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
                     rContext->Insert(PROP_CHAR_TRANSPARENCE, 
uno::makeAny(nTransparency));
                 }
             }
+            else if (nSprmId == NS_ooxml::LN_cntxtAlts_cntxtAlts)
+            {
+                pTextEffectsHandlerPtr->lcl_sprm(rSprm);
+                beans::PropertyValue aGrabBag = 
pTextEffectsHandlerPtr->getInteropGrabBag();
+                rContext->Insert(*aPropertyId, uno::makeAny(aGrabBag), true, 
CHAR_GRAB_BAG);
+            }
         }
     }
     break;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 3edffc00121f..760a923c1c00 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -844,6 +844,11 @@ void DomainMapper_Impl::PushSdt()
     m_xSdtStarts.push({bStart, OUString(), xCursor->getStart()});
 }
 
+const std::stack<BookmarkInsertPosition>& DomainMapper_Impl::GetSdtStarts() 
const
+{
+    return m_xSdtStarts;
+}
+
 void DomainMapper_Impl::PopSdt()
 {
     if (m_xSdtStarts.empty())
@@ -881,7 +886,23 @@ void DomainMapper_Impl::PopSdt()
         xContentControlProps->setPropertyValue("ShowingPlaceHolder",
                                                
uno::makeAny(m_pSdtHelper->GetShowingPlcHdr()));
     }
+
+    if (m_pSdtHelper->getControlType() == SdtControlType::checkBox)
+    {
+        xContentControlProps->setPropertyValue("Checkbox", uno::makeAny(true));
+
+        xContentControlProps->setPropertyValue("Checked", 
uno::makeAny(m_pSdtHelper->GetChecked()));
+
+        xContentControlProps->setPropertyValue("CheckedState",
+                                               
uno::makeAny(m_pSdtHelper->GetCheckedState()));
+
+        xContentControlProps->setPropertyValue("UncheckedState",
+                                               
uno::makeAny(m_pSdtHelper->GetUncheckedState()));
+    }
+
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
+
+    m_pSdtHelper->clear();
 }
 
 void    DomainMapper_Impl::PushProperties(ContextType eId)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 3b4602f252b5..67ed5b090e4e 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -716,8 +716,12 @@ public:
 
     /// Setter method for m_bSdt.
     void SetSdt(bool bSdt);
+
     void PushSdt();
     void PopSdt();
+    /// Gives access to the currently open run/inline SDTs.
+    const std::stack<BookmarkInsertPosition>& GetSdtStarts() const;
+
     /// Getter method for m_bSdt.
     bool GetSdt() const { return m_bSdt;}
     bool GetParaChanged() const { return m_bParaChanged;}
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 0d91a242c0d5..23c8ba0e4dc4 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -425,6 +425,21 @@ void SdtHelper::SetShowingPlcHdr() { m_bShowingPlcHdr = 
true; }
 
 bool SdtHelper::GetShowingPlcHdr() const { return m_bShowingPlcHdr; }
 
+void SdtHelper::SetChecked() { m_bChecked = true; }
+
+bool SdtHelper::GetChecked() const { return m_bChecked; }
+
+void SdtHelper::SetCheckedState(const OUString& rCheckedState) { 
m_aCheckedState = rCheckedState; }
+
+OUString SdtHelper::GetCheckedState() const { return m_aCheckedState; }
+
+void SdtHelper::SetUncheckedState(const OUString& rUncheckedState)
+{
+    m_aUncheckedState = rUncheckedState;
+}
+
+OUString SdtHelper::GetUncheckedState() const { return m_aUncheckedState; }
+
 void SdtHelper::clear()
 {
     m_aDropDownItems.clear();
@@ -434,6 +449,9 @@ void SdtHelper::clear()
     m_sDataBindingStoreItemID.clear();
     m_aGrabBag.clear();
     m_bShowingPlcHdr = false;
+    m_bChecked = false;
+    m_aCheckedState.clear();
+    m_aUncheckedState.clear();
 }
 
 } // namespace writerfilter::dmapper
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx 
b/writerfilter/source/dmapper/SdtHelper.hxx
index 578bb5edd4fd..dfc43c80fce8 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -43,6 +43,7 @@ enum class SdtControlType
     dropDown,
     plainText,
     richText,
+    checkBox,
     unsupported, // Sdt block is defined, but we still do not support such 
type of field
     unknown
 };
@@ -97,6 +98,15 @@ class SdtHelper final : public virtual SvRefBase
     /// Current contents are placeholder text.
     bool m_bShowingPlcHdr = false;
 
+    /// If this is a checkbox, is the checkbox checked?
+    bool m_bChecked = false;
+
+    /// If this is a checkbox, the value of a checked checkbox.
+    OUString m_aCheckedState;
+
+    /// If this is a checkbox, the value of an unchecked checkbox.
+    OUString m_aUncheckedState;
+
     /// Create and append the drawing::XControlShape, containing the various 
models.
     void createControlShape(css::awt::Size aSize,
                             css::uno::Reference<css::awt::XControlModel> 
const& xControlModel,
@@ -106,9 +116,6 @@ class SdtHelper final : public virtual SvRefBase
 
     void loadPropertiesXMLs();
 
-    /// Clear all collected attributes for futher reuse
-    void clear();
-
 public:
     explicit SdtHelper(DomainMapper_Impl& rDM_Impl,
                        css::uno::Reference<css::uno::XComponentContext> const& 
xContext);
@@ -162,6 +169,16 @@ public:
 
     void SetShowingPlcHdr();
     bool GetShowingPlcHdr() const;
+
+    void SetChecked();
+    bool GetChecked() const;
+    void SetCheckedState(const OUString& rCheckedState);
+    OUString GetCheckedState() const;
+    void SetUncheckedState(const OUString& rUncheckedState);
+    OUString GetUncheckedState() const;
+
+    /// Clear all collected attributes for further reuse
+    void clear();
 };
 
 } // namespace writerfilter::dmapper
diff --git a/writerfilter/source/dmapper/TextEffectsHandler.cxx 
b/writerfilter/source/dmapper/TextEffectsHandler.cxx
index 3288556c8979..d145c854fc80 100644
--- a/writerfilter/source/dmapper/TextEffectsHandler.cxx
+++ b/writerfilter/source/dmapper/TextEffectsHandler.cxx
@@ -66,6 +66,7 @@ OUString lclGetNameForElementId(sal_uInt32 aId)
         aIdMap[NS_ooxml::LN_CT_Props3D_extrusionClr]            = 
"extrusionClr";
         aIdMap[NS_ooxml::LN_CT_Props3D_contourClr]              = "contourClr";
         aIdMap[NS_ooxml::LN_CT_StylisticSets_styleSet]          = "styleSet";
+        aIdMap[NS_ooxml::LN_cntxtAlts_cntxtAlts]                = "cntxtAlts";
     }
     return aIdMap[aId];
 }
diff --git a/writerfilter/source/dmapper/TextEffectsHandler.hxx 
b/writerfilter/source/dmapper/TextEffectsHandler.hxx
index 22127c6c81b2..30a8435b2829 100644
--- a/writerfilter/source/dmapper/TextEffectsHandler.hxx
+++ b/writerfilter/source/dmapper/TextEffectsHandler.hxx
@@ -33,10 +33,6 @@ private:
 
     void convertElementIdToPropertyId(sal_Int32 aElementId);
 
-    // LoggedProperties
-    virtual void lcl_attribute(Id aName, Value& aValue) override;
-    virtual void lcl_sprm(Sprm& sprm) override;
-
 public:
     explicit TextEffectsHandler(sal_uInt32 aElementId);
     virtual ~TextEffectsHandler() override;
@@ -63,6 +59,10 @@ public:
     static OUString getNumSpacingString(sal_Int32 nType);
 
     static sal_uInt8 GetTextFillSolidFillAlpha(const 
css::beans::PropertyValue& rValue);
+
+    // LoggedProperties
+    virtual void lcl_attribute(Id aName, Value& aValue) override;
+    virtual void lcl_sprm(Sprm& sprm) override;
 };
 }
 
diff --git a/writerfilter/source/ooxml/model.xml 
b/writerfilter/source/ooxml/model.xml
index 04fb1934b8d5..38dd9ba15b08 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -4886,7 +4886,7 @@
       </define>
       <define name="CT_SdtCheckbox">
         <element name="checked">
-          <ref name="CT_String"/>
+          <ref name="CT_OnOff"/>
         </element>
         <element name="checkedState">
           <ref name="CT_String"/>
@@ -5260,8 +5260,9 @@
       <attribute name="id" tokenid="ooxml:CT_StyleSet_id"/>
       <attribute name="val" tokenid="ooxml:CT_StyleSet_val"/>
     </resource>
-    <resource name="CT_OnOff" resource="Properties">
-      <attribute name="val" tokenid="ooxml:CT_OnOff_val"/>
+    <resource name="CT_OnOff" resource="Value">
+      <attribute name="val" tokenid="ooxml:CT_OnOff_val" action="setValue"/>
+      <action name="start" action="setDefaultBooleanValue"/>
     </resource>
 
     <!-- Main element content -->

Reply via email to