offapi/com/sun/star/text/ContentControl.idl                      |    6 ++
 oox/source/token/tokens.txt                                      |    1 
 schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng      |    5 +
 sw/inc/formatcontentcontrol.hxx                                  |    7 ++
 sw/inc/unoprnms.hxx                                              |    1 
 sw/qa/core/unocore/unocore.cxx                                   |    2 
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx                       |    2 
 sw/source/core/txtnode/attrcontentcontrol.cxx                    |    2 
 sw/source/core/unocore/unocontentcontrol.cxx                     |   29 
++++++++++
 sw/source/core/unocore/unomap1.cxx                               |    1 
 sw/source/filter/ww8/docxattributeoutput.cxx                     |   16 +++++
 sw/source/filter/ww8/docxattributeoutput.hxx                     |    2 
 writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx               |    4 +
 writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx |binary
 writerfilter/source/dmapper/DomainMapper.cxx                     |   15 +++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx                |    5 +
 writerfilter/source/dmapper/SdtHelper.cxx                        |    5 +
 writerfilter/source/dmapper/SdtHelper.hxx                        |    6 ++
 writerfilter/source/ooxml/model.xml                              |    4 +
 xmloff/qa/unit/data/content-control-alias.fodt                   |    2 
 xmloff/qa/unit/text.cxx                                          |    5 +
 xmloff/source/text/txtparae.cxx                                  |    8 ++
 xmloff/source/text/xmlcontentcontrolcontext.cxx                  |   14 ++++
 xmloff/source/text/xmlcontentcontrolcontext.hxx                  |    1 
 24 files changed, 142 insertions(+), 1 deletion(-)

New commits:
commit 4c7a9650cc27ac3ac67dda108ffd74612f9cdb3c
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Fri Dec 2 10:48:46 2022 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Dec 21 07:56:31 2022 +0000

    tdf#151548 sw content controls: preserve tabIndex
    
    This has to be vital to keyboard navigation.
    Certainly it is good to have it imported
    before we start to consider tab-movements
    for form controls.
    
    All tabIndex 1's are processed (in placement order)
    and then the 2's etc. 0's are to be done last.
    
    XML_TAB_INDEX already existed in include/xmloff/xmltoken.hxx
    and "tab-index" already exists in xmloff/source/token/tokens.txt
    
    make CppunitTest_writerfilter_dmapper CPPUNIT_TEST_NAME=testSdtRunRichText
    make CppunitTest_sw_ooxmlexport17 
CPPUNIT_TEST_NAME=testDateContentControlExport
    make CppunitTest_sw_core_unocore CPPUNIT_TEST_NAME=testContentControlDate
    make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlExport
    make CppunitTest_xmloff_text CPPUNIT_TEST_NAME=testAliasContentControlImport
    
    No existing unit test found containing blockSDT with tabIndex.
    
    Change-Id: I8a958844e6192b079a2b22a62dedfd8739021f4a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143603
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144623
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/offapi/com/sun/star/text/ContentControl.idl 
b/offapi/com/sun/star/text/ContentControl.idl
index 59894741de2b..ce741d9b2926 100644
--- a/offapi/com/sun/star/text/ContentControl.idl
+++ b/offapi/com/sun/star/text/ContentControl.idl
@@ -128,6 +128,12 @@ service ContentControl
     */
     [optional, property] long Id;
 
+    /** Describes the order in which keyboard navigation moves between controls
+
+        @since LibreOffice 7.6
+    */
+    [optional, property] unsigned long TabIndex;
+
     /** Describes whether the control itself and/or its data can be modified 
or deleted by the user.
 
         @since LibreOffice 7.6
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index d1a40140add9..1b634835254c 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -5122,6 +5122,7 @@ tOff
 tR
 tab
 tabColor
+tabIndex
 tabLst
 tabRatio
 tabSelected
diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng 
b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
index 0acadbb8e71c..ff0019c1bc50 100644
--- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
+++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng
@@ -2944,6 +2944,11 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
           <rng:ref name="string"/>
         </rng:attribute>
       </rng:optional>
+      <rng:optional>
+        <rng:attribute name="loext:tab-index">
+          <rng:ref name="nonNegativeInteger"/>
+        </rng:attribute>
+      </rng:optional>
       <rng:optional>
         <rng:attribute name="loext:lock">
           <rng:ref name="string"/>
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index c0b200683277..9c142ed711f0 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -178,6 +178,9 @@ class SW_DLLPUBLIC SwContentControl : public 
sw::BroadcastingModify
     /// The id: just remembered.
     sal_Int32 m_nId = 0;
 
+    /// The tabIndex: just remembered.
+    sal_uInt32 m_nTabIndex = 0;
+
     /// The control and content locks: mostly just remembered.
     OUString m_aLock;
 
@@ -364,6 +367,10 @@ public:
 
     sal_Int32 GetId() const { return m_nId; }
 
+    void SetTabIndex(sal_uInt32 nTabIndex) { m_nTabIndex = nTabIndex; }
+
+    sal_uInt32 GetTabIndex() const { return m_nTabIndex; }
+
     // At the design level, define how the control should be locked. No effect 
at implementation lvl
     void SetLock(bool bLockContent, bool bLockControl);
     void SetLock(const OUString& rLock) { m_aLock = rLock; }
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index a850b76994f4..12f839c2b16a 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -891,6 +891,7 @@
 #define UNO_NAME_ALIAS "Alias"
 #define UNO_NAME_TAG "Tag"
 #define UNO_NAME_ID "Id"
+#define UNO_NAME_TAB_INDEX "TabIndex"
 #define UNO_NAME_LOCK "Lock"
 #define UNO_NAME_DATE_STRING "DateString"
 #endif
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index be5d74678e2e..2cb6c995e08b 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -574,6 +574,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlDate)
     xContentControlProps->setPropertyValue("Color", 
uno::Any(OUString("008000")));
     xContentControlProps->setPropertyValue("Alias", 
uno::Any(OUString("myalias")));
     xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag")));
+    xContentControlProps->setPropertyValue("TabIndex", 
uno::Any(sal_uInt32(1)));
     xContentControlProps->setPropertyValue("Lock", 
uno::Any(OUString("sdtContentLocked")));
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
 
@@ -600,6 +601,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlDate)
     CPPUNIT_ASSERT_EQUAL(OUString("008000"), pContentControl->GetColor());
     CPPUNIT_ASSERT_EQUAL(OUString("myalias"), pContentControl->GetAlias());
     CPPUNIT_ASSERT_EQUAL(OUString("mytag"), pContentControl->GetTag());
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(1), 
pContentControl->GetTabIndex());
     CPPUNIT_ASSERT_EQUAL(OUString("sdtContentLocked"), 
pContentControl->GetLock());
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index bb7f3d9458b6..72c78cebe79c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -300,6 +300,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport)
     xContentControlProps->setPropertyValue("Color", 
uno::Any(OUString("008000")));
     xContentControlProps->setPropertyValue("Alias", 
uno::Any(OUString("myalias")));
     xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("mytag")));
+    xContentControlProps->setPropertyValue("TabIndex", 
uno::Any(sal_uInt32(2)));
     xContentControlProps->setPropertyValue("Lock", 
uno::Any(OUString("sdtLocked")));
 
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
@@ -325,6 +326,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDateContentControlExport)
     assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w15:color", "val", "008000");
     assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:alias", "val", "myalias");
     assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tag", "val", "mytag");
+    assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:tabIndex", "val", "2");
     assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:lock", "val", "sdtLocked");
 }
 
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index 19fd922a439b..034529ce37b2 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -556,6 +556,8 @@ void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) 
const
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("tag"), 
BAD_CAST(m_aTag.toUtf8().getStr()));
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("id"),
                                       
BAD_CAST(OString::number(m_nId).getStr()));
+    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("tab-index"),
+                                      
BAD_CAST(OString::number(m_nTabIndex).getStr()));
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("lock"),
                                       BAD_CAST(m_aLock.toUtf8().getStr()));
 
diff --git a/sw/source/core/unocore/unocontentcontrol.cxx 
b/sw/source/core/unocore/unocontentcontrol.cxx
index 01b1771e6edf..ee8cebe913c5 100644
--- a/sw/source/core/unocore/unocontentcontrol.cxx
+++ b/sw/source/core/unocore/unocontentcontrol.cxx
@@ -178,6 +178,7 @@ public:
     OUString m_aAlias;
     OUString m_aTag;
     sal_Int32 m_nId;
+    sal_uInt32 m_nTabIndex;
     OUString m_aLock;
 
     Impl(SwXContentControl& rThis, SwDoc& rDoc, SwContentControl* 
pContentControl,
@@ -198,6 +199,7 @@ public:
         , m_bComboBox(false)
         , m_bDropDown(false)
         , m_nId(0)
+        , m_nTabIndex(0)
     {
         if (m_pContentControl)
         {
@@ -557,6 +559,7 @@ void SwXContentControl::AttachImpl(const 
uno::Reference<text::XTextRange>& xText
     pContentControl->SetAlias(m_pImpl->m_aAlias);
     pContentControl->SetTag(m_pImpl->m_aTag);
     pContentControl->SetId(m_pImpl->m_nId);
+    pContentControl->SetTabIndex(m_pImpl->m_nTabIndex);
     pContentControl->SetLock(m_pImpl->m_aLock);
 
     SwFormatContentControl aContentControl(pContentControl, nWhich);
@@ -1048,6 +1051,21 @@ void SAL_CALL SwXContentControl::setPropertyValue(const 
OUString& rPropertyName,
             }
         }
     }
+    else if (rPropertyName == UNO_NAME_TAB_INDEX)
+    {
+        sal_uInt32 nValue = 0;
+        if (rValue >>= nValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_nTabIndex = nValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetTabIndex(nValue);
+            }
+        }
+    }
     else if (rPropertyName == UNO_NAME_LOCK)
     {
         OUString aValue;
@@ -1325,6 +1343,17 @@ uno::Any SAL_CALL 
SwXContentControl::getPropertyValue(const OUString& rPropertyN
             aRet <<= m_pImpl->m_pContentControl->GetId();
         }
     }
+    else if (rPropertyName == UNO_NAME_TAB_INDEX)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_nTabIndex;
+        }
+        else
+        {
+            aRet <<= m_pImpl->m_pContentControl->GetTabIndex();
+        }
+    }
     else if (rPropertyName == UNO_NAME_LOCK)
     {
         if (m_pImpl->m_bIsDescriptor)
diff --git a/sw/source/core/unocore/unomap1.cxx 
b/sw/source/core/unocore/unomap1.cxx
index 0ae874b3b9e1..5e96a882029a 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -1048,6 +1048,7 @@ const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetContentControlProper
         { u"" UNO_NAME_ALIAS, 0, cppu::UnoType<OUString>::get(), 
PROPERTY_NONE, 0 },
         { u"" UNO_NAME_TAG, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 
0 },
         { u"" UNO_NAME_ID, 0, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, 
0 },
+        { u"" UNO_NAME_TAB_INDEX, 0, cppu::UnoType<sal_uInt32>::get(), 
PROPERTY_NONE, 0 },
         { u"" UNO_NAME_LOCK, 0, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 
0 },
         { u"" UNO_NAME_DATE_STRING, 0, cppu::UnoType<OUString>::get(), 
PropertyAttribute::READONLY, 0 },
         { u"", 0, css::uno::Type(), 0, 0 }
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 73d01152dfb5..20dd8cf8738f 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -624,6 +624,7 @@ void SdtBlockHelper::DeleteAndResetTheLists()
     if (!m_aColor.isEmpty())
         m_aColor.clear();
     m_bShowingPlaceHolder = false;
+    m_nTabIndex = 0;
     m_bHasId = false;
 }
 
@@ -731,6 +732,10 @@ void 
SdtBlockHelper::WriteExtraParams(::sax_fastparser::FSHelperPtr& pSerializer
     if (!m_aTag.isEmpty())
         pSerializer->singleElementNS(XML_w, XML_tag, FSNS(XML_w, XML_val), 
m_aTag);
 
+    if (m_nTabIndex)
+        pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, XML_val),
+                                     OString::number(m_nTabIndex));
+
     if (!m_aLock.isEmpty())
         pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val), 
m_aLock);
 }
@@ -847,6 +852,11 @@ void SdtBlockHelper::GetSdtParamsFromGrabBag(const 
uno::Sequence<beans::Property
             if (!(aPropertyValue.Value >>= m_aTag))
                 SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected 
sdt tag value");
         }
+        else if (aPropertyValue.Name == "ooxml:CT_SdtPr_tabIndex" && 
!m_nTabIndex)
+        {
+            if (!(aPropertyValue.Value >>= m_nTabIndex))
+                SAL_WARN("sw.ww8", "DocxAttributeOutput::GrabBag: unexpected 
sdt tabIndex value");
+        }
         else if (aPropertyValue.Name == "ooxml:CT_SdtPr_lock" && 
m_aLock.isEmpty())
         {
             if (!(aPropertyValue.Value >>= m_aLock))
@@ -2411,6 +2421,12 @@ void DocxAttributeOutput::WriteContentControlStart()
                                        
OString::number(m_pContentControl->GetId()));
     }
 
+    if (m_pContentControl->GetTabIndex())
+    {
+        m_pSerializer->singleElementNS(XML_w, XML_tabIndex, FSNS(XML_w, 
XML_val),
+                                       
OString::number(m_pContentControl->GetTabIndex()));
+    }
+
     if (!m_pContentControl->GetLock().isEmpty())
     {
         m_pSerializer->singleElementNS(XML_w, XML_lock, FSNS(XML_w, XML_val),
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index 8191cfb523cf..e5b00eb4c050 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -131,6 +131,7 @@ public:
         : m_bHasId(false)
         , m_bStartedSdt(false)
         , m_bShowingPlaceHolder(false)
+        , m_nTabIndex(0)
         , m_nSdtPrToken(0)
     {}
 
@@ -145,6 +146,7 @@ public:
     bool m_bShowingPlaceHolder;
     OUString m_aAlias;
     OUString m_aTag;
+    sal_Int32 m_nTabIndex;
     OUString m_aLock;
     sal_Int32 m_nSdtPrToken;
 
diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx 
b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
index f773991f7e02..3595eb3d22f0 100644
--- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx
@@ -95,6 +95,10 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText)
     xContentControlProps->getPropertyValue("Tag") >>= aTag;
     // This was empty.
     CPPUNIT_ASSERT_EQUAL(OUString("mytag"), aTag);
+    sal_uInt32 nTabIndex = 0;
+    xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex;
+    // This was 0
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(5), nTabIndex);
     OUString aLock;
     xContentControlProps->getPropertyValue("Lock") >>= aLock;
     // This was empty.
diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx 
b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx
index aabc745bcf0e..ca980abb0356 100644
Binary files a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx 
and b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-rich-text.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index d98b2d3491e3..3301658eaefb 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2808,6 +2808,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
     case NS_ooxml::LN_CT_SdtPr_showingPlcHdr:
     case NS_ooxml::LN_CT_SdtPr_color:
     case NS_ooxml::LN_CT_SdtPr_tag:
+    case NS_ooxml::LN_CT_SdtPr_tabIndex:
     case NS_ooxml::LN_CT_SdtPr_lock:
     {
         if (!m_pImpl->GetSdtStarts().empty())
@@ -2846,6 +2847,12 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
                 break;
             }
 
+            if (nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex)
+            {
+                m_pImpl->m_pSdtHelper->SetTabIndex(nIntValue);
+                break;
+            }
+
             if (nSprmId == NS_ooxml::LN_CT_SdtPr_lock)
             {
                 m_pImpl->m_pSdtHelper->SetLock(sStringValue);
@@ -2899,6 +2906,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
             case NS_ooxml::LN_CT_SdtPr_id:          sName = 
"ooxml:CT_SdtPr_id"; break;
             case NS_ooxml::LN_CT_SdtPr_alias:       sName = 
"ooxml:CT_SdtPr_alias"; break;
             case NS_ooxml::LN_CT_SdtPr_tag:         sName = 
"ooxml:CT_SdtPr_tag"; break;
+            case NS_ooxml::LN_CT_SdtPr_tabIndex:    sName = 
"ooxml:CT_SdtPr_tabIndex"; break;
             case NS_ooxml::LN_CT_SdtPr_lock:        sName = 
"ooxml:CT_SdtPr_lock"; break;
             case NS_ooxml::LN_CT_SdtPlaceholder_docPart: sName = 
"ooxml:CT_SdtPlaceholder_docPart"; break;
             case NS_ooxml::LN_CT_SdtPr_showingPlcHdr: sName = 
"ooxml:CT_SdtPr_showingPlcHdr"; break;
@@ -2937,6 +2945,13 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
             aValue.Value <<= bool(nIntValue);
             m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue);
         }
+        else if (nSprmId == NS_ooxml::LN_CT_SdtPr_tabIndex)
+        {
+            beans::PropertyValue aValue;
+            aValue.Name = sName;
+            aValue.Value <<= nIntValue;
+            m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue);
+        }
         else
             m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag());
         
m_pImpl->m_pSdtHelper->setOutsideAParagraph(m_pImpl->IsOutsideAParagraph());
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 71f73d3fedea..0946a5eb8c9c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -948,6 +948,11 @@ void DomainMapper_Impl::PopSdt()
         xContentControlProps->setPropertyValue("Id", 
uno::Any(m_pSdtHelper->GetId()));
     }
 
+    if (m_pSdtHelper->GetTabIndex())
+    {
+        xContentControlProps->setPropertyValue("TabIndex", 
uno::Any(m_pSdtHelper->GetTabIndex()));
+    }
+
     if (!m_pSdtHelper->GetLock().isEmpty())
     {
         xContentControlProps->setPropertyValue("Lock", 
uno::Any(m_pSdtHelper->GetLock()));
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx 
b/writerfilter/source/dmapper/SdtHelper.cxx
index 9a72ef5e1f3a..a80c03ed4ba5 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -460,6 +460,7 @@ void SdtHelper::clear()
     m_aAlias.clear();
     m_aTag.clear();
     m_nId = 0;
+    m_nTabIndex = 0;
     m_aLock.clear();
 }
 
@@ -486,6 +487,10 @@ void SdtHelper::SetId(sal_Int32 nId) { m_nId = nId; }
 
 sal_Int32 SdtHelper::GetId() const { return m_nId; }
 
+void SdtHelper::SetTabIndex(sal_uInt32 nTabIndex) { m_nTabIndex = nTabIndex; }
+
+sal_uInt32 SdtHelper::GetTabIndex() const { return m_nTabIndex; }
+
 void SdtHelper::SetLock(const OUString& rLock) { m_aLock = rLock; }
 
 const OUString& SdtHelper::GetLock() const { return m_aLock; }
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx 
b/writerfilter/source/dmapper/SdtHelper.hxx
index 9504be5ddd57..38fda74ec55f 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -134,6 +134,9 @@ class SdtHelper final : public virtual SvRefBase
     /// <w:sdtPr>'s <w:id w:val="...">.
     sal_Int32 m_nId = 0;
 
+    /// <w:sdtPr>'s <w:tabIndex w:val="...">.
+    sal_uInt32 m_nTabIndex = 0;
+
     /// <w:sdtPr>'s <w:lock w:val="...">.
     OUString m_aLock;
 
@@ -225,6 +228,9 @@ public:
     void SetId(sal_Int32 nId);
     sal_Int32 GetId() const;
 
+    void SetTabIndex(sal_uInt32 nTabIndex);
+    sal_uInt32 GetTabIndex() const;
+
     void SetLock(const OUString& rLock);
     const OUString& GetLock() const;
 
diff --git a/writerfilter/source/ooxml/model.xml 
b/writerfilter/source/ooxml/model.xml
index 38dd9ba15b08..833af5f1aa27 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -13972,6 +13972,9 @@
           <element name="id">
             <ref name="CT_DecimalNumber"/>
           </element>
+          <element name="tabIndex">
+            <ref name="CT_DecimalNumber"/>
+          </element>
           <element name="tag">
             <ref name="CT_String"/>
           </element>
@@ -18269,6 +18272,7 @@
       <element name="dataBinding" tokenid="ooxml:CT_SdtPr_dataBinding"/>
       <element name="temporary" tokenid="ooxml:CT_SdtPr_temporary"/>
       <element name="id" tokenid="ooxml:CT_SdtPr_id"/>
+      <element name="tabIndex" tokenid="ooxml:CT_SdtPr_tabIndex"/>
       <element name="tag" tokenid="ooxml:CT_SdtPr_tag"/>
       <element name="equation" tokenid="ooxml:CT_SdtPr_equation"/>
       <element name="comboBox" tokenid="ooxml:CT_SdtPr_comboBox"/>
diff --git a/xmloff/qa/unit/data/content-control-alias.fodt 
b/xmloff/qa/unit/data/content-control-alias.fodt
index 8f541bef42cc..48fdc7b9436c 100644
--- a/xmloff/qa/unit/data/content-control-alias.fodt
+++ b/xmloff/qa/unit/data/content-control-alias.fodt
@@ -2,7 +2,7 @@
 <office:document xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
   <office:body>
     <office:text>
-      <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" 
loext:lock="sdtContentLocked">test</loext:content-control></text:p>
+      <text:p><loext:content-control loext:alias="my alias" loext:tag="my tag" 
loext:tab-index="4" 
loext:lock="sdtContentLocked">test</loext:content-control></text:p>
     </office:text>
   </office:body>
 </office:document>
diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx
index a57bbc55d4dc..9d6be54c5e70 100644
--- a/xmloff/qa/unit/text.cxx
+++ b/xmloff/qa/unit/text.cxx
@@ -849,6 +849,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, 
testAliasContentControlExport)
     uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
     xContentControlProps->setPropertyValue("Alias", uno::Any(OUString("my 
alias")));
     xContentControlProps->setPropertyValue("Tag", uno::Any(OUString("my 
tag")));
+    xContentControlProps->setPropertyValue("TabIndex", 
uno::Any(sal_uInt32(3)));
     xContentControlProps->setPropertyValue("Lock", 
uno::Any(OUString("unlocked")));
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
 
@@ -871,6 +872,7 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, 
testAliasContentControlExport)
     // i.e. alias was lost on export.
     assertXPath(pXmlDoc, "//loext:content-control", "alias", "my alias");
     assertXPath(pXmlDoc, "//loext:content-control", "tag", "my tag");
+    assertXPath(pXmlDoc, "//loext:content-control", "tab-index", "3");
     assertXPath(pXmlDoc, "//loext:content-control", "lock", "unlocked");
 }
 
@@ -937,6 +939,9 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, 
testAliasContentControlImport)
     OUString aTag;
     xContentControlProps->getPropertyValue("Tag") >>= aTag;
     CPPUNIT_ASSERT_EQUAL(OUString("my tag"), aTag);
+    sal_uInt32 nTabIndex;
+    xContentControlProps->getPropertyValue("TabIndex") >>= nTabIndex;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(4), nTabIndex);
     OUString aLock;
     xContentControlProps->getPropertyValue("Lock") >>= aLock;
     CPPUNIT_ASSERT_EQUAL(OUString("sdtContentLocked"), aLock);
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index e46cbfc68649..b90b7318a07f 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -3989,6 +3989,14 @@ void XMLTextParagraphExport::ExportContentControl(
             GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
         }
 
+        sal_uInt32 nTabIndex;
+        xPropertySet->getPropertyValue("TabIndex") >>= nTabIndex;
+        if (nTabIndex)
+        {
+            GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAB_INDEX,
+                                     OUString::number(nTabIndex));
+        }
+
         OUString aLock;
         xPropertySet->getPropertyValue("Lock") >>= aLock;
         if (!aLock.isEmpty())
diff --git a/xmloff/source/text/xmlcontentcontrolcontext.cxx 
b/xmloff/source/text/xmlcontentcontrolcontext.cxx
index d08d3f02cf32..40ea1157b43d 100644
--- a/xmloff/source/text/xmlcontentcontrolcontext.cxx
+++ b/xmloff/source/text/xmlcontentcontrolcontext.cxx
@@ -49,6 +49,7 @@ void XMLContentControlContext::startFastElement(
     for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
     {
         bool bTmp = false;
+        sal_Int32 nTmp = 0;
 
         switch (rIter.getToken())
         {
@@ -151,6 +152,14 @@ void XMLContentControlContext::startFastElement(
                 m_aTag = rIter.toString();
                 break;
             }
+            case XML_ELEMENT(LO_EXT, XML_TAB_INDEX):
+            {
+                if (sax::Converter::convertNumber(nTmp, rIter.toView()))
+                {
+                    m_nTabIndex = nTmp;
+                }
+                break;
+            }
             case XML_ELEMENT(LO_EXT, XML_LOCK):
             {
                 m_aLock = rIter.toString();
@@ -267,6 +276,11 @@ void XMLContentControlContext::endFastElement(sal_Int32)
         xPropertySet->setPropertyValue("Tag", uno::Any(m_aTag));
     }
 
+    if (m_nTabIndex)
+    {
+        xPropertySet->setPropertyValue("TabIndex", uno::Any(m_nTabIndex));
+    }
+
     if (!m_aLock.isEmpty())
     {
         xPropertySet->setPropertyValue("Lock", uno::Any(m_aLock));
diff --git a/xmloff/source/text/xmlcontentcontrolcontext.hxx 
b/xmloff/source/text/xmlcontentcontrolcontext.hxx
index f0b1eea0b010..44abe71d6a08 100644
--- a/xmloff/source/text/xmlcontentcontrolcontext.hxx
+++ b/xmloff/source/text/xmlcontentcontrolcontext.hxx
@@ -53,6 +53,7 @@ class XMLContentControlContext : public SvXMLImportContext
     bool m_bDropDown = false;
     OUString m_aAlias;
     OUString m_aTag;
+    sal_uInt32 m_nTabIndex = 0;
     OUString m_aLock;
 
 public:

Reply via email to