[Libreoffice-commits] core.git: Branch 'feature/cib_contract3753' - 19 commits - filter/source include/oox oox/source sd/uiconfig sw/CppunitTest_sw_ooxmlexport4.mk sw/inc sw/qa sw/source translations vcl/uiconfig writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Thu Aug 13 15:04:26 UTC 2020


Rebased ref, commits from common ancestor:
commit 8a6a1827e046f28a1236168c30db060a16a813c4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 13 11:07:37 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:55:53 2020 +0200

    sw: DOCX export: for soft-page-breaks, export continuous section breaks
    
    When a section break is produced based on layout information such as
    soft-page-break and follow page style, it's a bad idea to generate a
    page break because the break may be in a different position in Word,
    particularly if it was inside a fieldmark instruction.
    
    It wouldn't work that well to ignore such page breaks in
    MSWordExportBase::NeedTextNodeSplit() because then they would be created
    when reaching the next node anyway, via FindPageDesc() fall-back to
    layout.
    
    Unfortunately this breaks the test tdf113849_evenAndOddHeaders.odt
    which has a page style with follow-page-style on the first page; on
    re-import from DOCX, the continuous section is now no longer converted
    to a page break, so pages 2-3 have the wrong header/footers... this
    seems impossible to fix in general in the import because it doesn't know
    whether the continuous section break coincides with a layout page break.
    
    Arguably this worked before mostly by accident? tdf#113849 isn't about
    this afaics... Change the test file to have an explicit page break
    there, which round-trips as intended. The real fix would be adding
    continuous page style change to Writer i guess...
    
    Change-Id: I00ffe3971607c148a7d5c13b89afb936718611c0

diff --git a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt
index d9aa0ae23541..ae9b2af14ee7 100644
Binary files a/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt and b/sw/qa/extras/ooxmlexport/data/tdf113849_evenAndOddHeaders.odt differ
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index a212f4e5c9b8..74f06116484a 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -619,7 +619,8 @@ sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
 
 void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
         const SwNode& rNd, const SwFormatPageDesc* pNewPgDescFormat,
-        const SwPageDesc* pNewPgDesc )
+        const SwPageDesc* pNewPgDesc,
+        bool const bViaLayout)
 {
     // tell the attribute output that we are ready to write the section
     // break [has to be output inside paragraph properties]
@@ -632,13 +633,12 @@ void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
 
     if ( pNewPgDescFormat )
     {
-        m_pSections->AppendSection( *pNewPgDescFormat, rNd, pFormat, nLnNm );
+        m_pSections->AppendSection(*pNewPgDescFormat, rNd, pFormat, nLnNm, bViaLayout);
     }
     else if ( pNewPgDesc )
     {
-        m_pSections->AppendSection( pNewPgDesc, rNd, pFormat, nLnNm );
+        m_pSections->AppendSection(pNewPgDesc, rNd, pFormat, nLnNm, bViaLayout);
     }
-
 }
 
 void DocxExport::InitStyles()
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 00b908dc7efa..35e37a98ae39 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -218,7 +218,8 @@ protected:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) override;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) override;
 
 private:
     /// Setup pStyles and write styles.xml
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 366cc18b3b0c..0e8733b48d63 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -948,7 +948,7 @@ ErrCode RtfExport::ExportDocument_Impl()
 
 void RtfExport::PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
                                    const SwFormatPageDesc* pNewPgDescFormat,
-                                   const SwPageDesc* pNewPgDesc)
+                                   const SwPageDesc* pNewPgDesc, bool const)
 {
     const SwSectionFormat* pFormat = GetSectionFormat(rNd);
     const sal_uLong nLnNm = GetSectionLineNo(pSet, rNd);
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index 055aa50ff04e..527574ad701e 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -125,8 +125,8 @@ protected:
 
     /// Get ready for a new section.
     void PrepareNewPageDesc(const SfxItemSet* pSet, const SwNode& rNd,
-                            const SwFormatPageDesc* pNewPgDescFormat,
-                            const SwPageDesc* pNewPgDesc) override;
+                            const SwFormatPageDesc* pNewPgDescFormat, const SwPageDesc* pNewPgDesc,
+                            bool bViaLayout) override;
 
     /// Return value indicates if an inherited outline numbering is suppressed.
     bool DisallowInheritingOutlineNumbering(const SwFormat& rFormat) override;
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 36026312a332..b97c6f7950d0 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2742,7 +2742,7 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode )
                 // too.
                 const SwPageDesc* pNextPageDesc = m_pCurrentPageDesc->GetFollow();
                 assert(pNextPageDesc);
-                PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc);
+                PrepareNewPageDesc( rNode.GetpSwAttrSet(), rNode, nullptr , pNextPageDesc, true);
             }
         }
         else if (!bNeedParaSplit)
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
index eb06b97195bb..e264d51a1ff2 100644
--- a/sw/source/filter/ww8/wrtw8sty.cxx
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -1092,12 +1092,13 @@ const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
 }
 
 void MSWordSections::AppendSection( const SwPageDesc* pPd,
-    const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo, bool bIsFirstParagraph )
+    const SwSectionFormat*const pSectionFormat, sal_uLong const nLnNumRestartNo,
+    bool const bIsFirstParagraph, bool const bIsContinuous)
 {
     if (HeaderFooterWritten()) {
         return; // #i117955# prevent new sections in endnotes
     }
-    aSects.emplace_back( pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph );
+    aSects.emplace_back(pPd, pSectionFormat, nLnNumRestartNo, boost::none, nullptr, bIsFirstParagraph, bIsContinuous);
     NeedsDocumentProtected( aSects.back() );
 }
 
@@ -1112,13 +1113,14 @@ void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
 }
 
 void MSWordSections::AppendSection( const SwFormatPageDesc& rPD,
-    const SwNode& rNd, const SwSectionFormat* pSectionFormat, sal_uLong nLnNumRestartNo )
+    const SwNode& rNd, const SwSectionFormat*const pSectionFormat,
+    sal_uLong const nLnNumRestartNo, bool const bIsContinuous)
 {
     if (HeaderFooterWritten()) {
         return; // #i117955# prevent new sections in endnotes
     }
 
-    WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd );
+    WW8_SepInfo aI(rPD.GetPageDesc(), pSectionFormat, nLnNumRestartNo, rPD.GetNumOffset(), &rNd, false, bIsContinuous);
 
     aSects.push_back( aI );
     NeedsDocumentProtected( aI );
@@ -1548,9 +1550,9 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt
     /*  sprmSBkc, break code:   0 No break, 1 New column
         2 New page, 3 Even page, 4 Odd page
         */
-    sal_uInt8 nBreakCode = 2;            // default start new page
+    sal_uInt8 nBreakCode = rSepInfo.isContinuous ? 0 : 2; // default start new page
     bool bOutPgDscSet = true, bLeftRightPgChain = false, bOutputStyleItemSet = false;
-    bool bEnsureHeaderFooterWritten = rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph;
+    bool bEnsureHeaderFooterWritten = (rSepInfo.pSectionFormat && rSepInfo.bIsFirstParagraph) || rSepInfo.isContinuous;
     const SwFrameFormat* pPdFormat = &pPd->GetMaster();
     if ( rSepInfo.pSectionFormat )
     {
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 3f64071e2120..0e36006b9794 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -181,13 +181,16 @@ struct WW8_SepInfo
     sal_uLong const  nLnNumRestartNo;
     ::boost::optional<sal_uInt16> const oPgRestartNo;
     bool const bIsFirstParagraph;
+    bool isContinuous;
 
     WW8_SepInfo( const SwPageDesc* pPD, const SwSectionFormat* pFormat,
                  sal_uLong nLnRestart, ::boost::optional<sal_uInt16> oPgRestart = boost::none,
-                 const SwNode* pNd = nullptr, bool bIsFirstPara = false )
+                 const SwNode* pNd = nullptr, bool bIsFirstPara = false,
+                 bool bIsContinuous = false)
         : pPageDesc( pPD ), pSectionFormat( pFormat ), pPDNd( pNd ),
           nLnNumRestartNo( nLnRestart ), oPgRestartNo( oPgRestart ),
           bIsFirstParagraph( bIsFirstPara )
+        , isContinuous(bIsContinuous)
     {}
 
     bool IsProtected() const;
@@ -216,11 +219,13 @@ public:
     void AppendSection( const SwPageDesc* pPd,
                     const SwSectionFormat* pSectionFormat,
                     sal_uLong nLnNumRestartNo,
-                    bool bIsFirstParagraph = false );
+                    bool bIsFirstParagraph = false,
+                    bool bIsContinuous = false);
     void AppendSection( const SwFormatPageDesc& rPd,
                     const SwNode& rNd,
                     const SwSectionFormat* pSectionFormat,
-                    sal_uLong nLnNumRestartNo );
+                    sal_uLong nLnNumRestartNo,
+                    bool bIsContinuous = false);
 
     /// Number of columns based on the most recent WW8_SepInfo.
     sal_uInt16 CurrentNumberOfColumns( const SwDoc &rDoc ) const;
@@ -857,7 +862,8 @@ protected:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) = 0;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) = 0;
 
     /// Return value indicates if an inherited outline numbering is suppressed.
     virtual bool DisallowInheritingOutlineNumbering(const SwFormat &rFormat) = 0;
@@ -1124,7 +1130,8 @@ public:
     virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
                                      const SwNode& rNd,
                                      const SwFormatPageDesc* pNewPgDescFormat,
-                                     const SwPageDesc* pNewPgDesc ) override;
+                                     const SwPageDesc* pNewPgDesc,
+                                     bool bViaLayout ) override;
 
     static void Out_BorderLine(ww::bytes& rO, const ::editeng::SvxBorderLine* pLine,
         sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9,
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 80efe524b472..952f6ab140db 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -457,7 +457,9 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
     //section.
     bool bBreakSet = false;
 
-    const SwPageDesc * pPageDesc = rNd.FindPageDesc();
+    size_t idx(0);
+    const SwPageDesc * pPageDesc = rNd.FindPageDesc(&idx);
+    bool isViaLayout(idx == rNd.GetIndex());
 
     // Even if pAktPageDesc != pPageDesc ,it might be because of the different header & footer types.
     if (m_pCurrentPageDesc != pPageDesc)
@@ -524,6 +526,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
              static_cast<const SwFormatPageDesc*>(pItem)->GetRegisteredIn() != nullptr)
         {
             bBreakSet = true;
+            assert(!isViaLayout);
             bNewPageDesc = true;
             pPgDesc = static_cast<const SwFormatPageDesc*>(pItem);
             m_pCurrentPageDesc = pPgDesc->GetPageDesc();
@@ -551,6 +554,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
                 }
             }
             bBreakSet = true;
+            isViaLayout = false;
 
             if ( !bRemoveHardBreakInsideTable )
             {
@@ -617,7 +621,7 @@ void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode
 
     if ( bNewPageDesc && m_pCurrentPageDesc )
     {
-        PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc );
+        PrepareNewPageDesc(pSet, rNd, pPgDesc, m_pCurrentPageDesc, isViaLayout);
     }
     m_bBreakBefore = false;
     m_bPrevTextNodeIsEmpty = isTextNodeEmpty ;
@@ -632,7 +636,7 @@ bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTex
          m_pCurrentPageDesc &&
          m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() )
     {
-        PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() );
+        PrepareNewPageDesc(pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow(), true);
         bRet = true;
     }
 
@@ -670,7 +674,8 @@ sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNo
 void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,
                                       const SwNode& rNd,
                                       const SwFormatPageDesc* pNewPgDescFormat,
-                                      const SwPageDesc* pNewPgDesc )
+                                      const SwPageDesc* pNewPgDesc,
+                                      bool const )
 {
     // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding
     // position by the occurrences of PageDesc attributes. The construction and
commit 0d28b0c9f858ab26a0f194920d5196123eb6f106
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 12 17:07:18 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:54:22 2020 +0200

    sw: MS Word export: don't insert section breaks in field instructions
    
    MSWordExportBase::NeedTextNodeSplit() simply uses the soft-page-break
    positions to potentially insert section breaks - but now that Writer can
    display field instructions, it's quite silly to insert section breaks
    inside them.
    
    Change-Id: Ie57e6281a0287aac36984e5467920852db19a8ad

diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index f7dc3e2207d2..36026312a332 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -2165,7 +2165,29 @@ bool MSWordExportBase::NeedSectionBreak( const SwNode& rNd ) const
 
 bool MSWordExportBase::NeedTextNodeSplit( const SwTextNode& rNd, SwSoftPageBreakList& pList ) const
 {
-    rNd.fillSoftPageBreakList( pList );
+    SwSoftPageBreakList tmp;
+    rNd.fillSoftPageBreakList(tmp);
+    // hack: move the break behind any field marks; currently we can't hide the
+    // field mark instruction so the layout position is quite meaningless
+    IDocumentMarkAccess const& rIDMA(*rNd.GetDoc()->getIDocumentMarkAccess());
+    sal_Int32 pos(-1);
+    for (auto const& it : tmp)
+    {
+        if (pos < it) // previous one might have skipped over it
+        {
+            pos = it;
+            while (auto const*const pMark = rIDMA.getFieldmarkFor(SwPosition(const_cast<SwTextNode&>(rNd), pos)))
+            {
+                if (pMark->GetMarkEnd().nNode != rNd)
+                {
+                    pos = rNd.Len(); // skip everything
+                    break;
+                }
+                pos = pMark->GetMarkEnd().nContent.GetIndex(); // no +1, it's behind the char
+            }
+            pList.insert(pos);
+        }
+    }
     pList.insert(0);
     pList.insert( rNd.GetText().getLength() );
     return pList.size() > 2 && NeedSectionBreak( rNd );
commit 16d93e92085a47614f251d084f03fba517cae045
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 12 16:32:07 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:53:04 2020 +0200

    sw: avoid assert when deletion starts at fieldmark end
    
    This hit assert(bSavePos && bSaveOtherPos);
    
    Tweak SwUndoSaveContent::DelContentIndex() for fieldmarks to only accept
    an equal end position if the start position was in range as well.
    
    (regression from 24fd14b387dca458a1b6e9415e936d26562ddb1e)
    
    Change-Id: If6c9b049193bb7f1bc39ec66d1c965512f9d6ec1

diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index c37cffbaf9f8..bfea81a886b6 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1097,12 +1097,14 @@ void SwUndoSaveContent::DelContentIndex( const SwPosition& rMark,
                     if( pBkmk->IsExpanded() &&
                         *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd )
                     {
-                        if ( bSavePos || bSaveOtherPos
+                        assert(!bSaveOtherPos);
+                        if (   bSavePos
                             || (*pStt < pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() < *pEnd)
-                            || type == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK
-                            || type == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK
-                            || type == IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK
-                            || type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK)
+                            || (bMaybe
+                                && (   type == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK
+                                    || type == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK
+                                    || type == IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK
+                                    || type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK)))
                         {
                             if( bMaybe )
                                 bSavePos = true;
commit 5ef139dc303d38d719f35efdedaf38b8e2e150bc
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:12:04 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:51:01 2020 +0200

    sw: HACK to disble DrawingML export for rotated text shapes
    
    Change-Id: I7542d0dd000b974ce490b9b81f3d85412e2409f2

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 9a771a5f81b7..70b63e251495 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -444,9 +444,11 @@ DECLARE_OOXMLEXPORT_TEST(testRot90Fliph, "rot90-fliph.docx")
     // The problem was that a shape rotation of 90° got turned into 270° after roundtrip.
     if (xmlDocPtr pXmlDoc = parseExport("word/document.xml"))
     {
+#if 0
         assertXPath(pXmlDoc, "//a:xfrm", "flipH", "1");
         // This was 16200000 (270 * 60000).
         assertXPath(pXmlDoc, "//a:xfrm", "rot", "5400000");
+#endif
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 3218ca060469..09ff67d0fb58 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -42,6 +42,7 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
     if (!pXmlDocument)
         return;
 
+#if 0
     assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
         "/wp:positionH/wp:posOffset", "-480060");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
@@ -60,13 +61,14 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
         "/wp:positionV/wp:posOffset", "1080135");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
         "/wp:positionV", "relativeFrom", "page");
+#endif
 
     // now test text rotation -> VML writing direction
-    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
     // text wrap -> VML
-    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape/w10:wrap", "type", "none");
     // vertical alignment -> VML
-    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:pict/v:shape", "style");
     CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
 }
 
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 7cacc4eb3173..b86c64daeb24 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -16,6 +16,7 @@
 #include <editeng/opaqitem.hxx>
 #include <editeng/boxitem.hxx>
 #include <svx/svdogrp.hxx>
+#include <svx/svdotext.hxx>
 #include <oox/token/namespaces.hxx>
 #include <textboxhelper.hxx>
 #include <fmtanchr.hxx>
@@ -983,6 +984,24 @@ bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XSha
     return true;
 }
 
+bool lcl_isRotatedText(SdrObject const& rShape, uno::Reference<drawing::XShape> const& xShape)
+{
+    uno::Reference<beans::XPropertySet> const xProps(xShape, uno::UNO_QUERY);
+    sal_Int32 nRotateAngle = sal_Int32();
+    if (!dynamic_cast<SdrTextObj const*>(&rShape)
+        || !xProps->getPropertySetInfo()->hasPropertyByName("RotateAngle")
+        || !(xProps->getPropertyValue("RotateAngle") >>= nRotateAngle))
+    {
+        return false;
+    }
+    if (nRotateAngle == 9000) // is it enough, or should it be any angle != 0?
+    {
+        SAL_INFO("sw.ww8", "HACK: forcing rotated shape to VML only");
+        return true;
+    }
+    return false;
+}
+
 void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
                                           const SwFrameFormat& rFrameFormat, int nAnchorId)
 {
@@ -1001,6 +1020,7 @@ void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj,
     // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
     // A common service created in util to check for VML shapes which are allowed to have textbox in content
     if ((msfilter::util::HasTextBoxContent(eShapeType)) && Impl::isSupportedDMLShape(xShape)
+        && !lcl_isRotatedText(*sdrObj, xShape)
         && (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML
     {
         m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent);
commit e6e8d7cdef5d3d1448f13a9dc68340bd92afc37a
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:50:12 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:51:00 2020 +0200

    oox: VML export: convert ESCHER_Prop_AnchorText to v-text-anchor
    
    Change-Id: I903cac8d7b02138680613b5a1b6dab4b1c448158

diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 555796c47a9c..ee93cf32bd27 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,47 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
                 break;
 
+            case ESCHER_Prop_AnchorText: // 135
+                {
+                    char const* pValue(nullptr);
+                    switch (opt.nPropValue)
+                    {
+                        case ESCHER_AnchorTop:
+                            pValue = "top";
+                        break;
+                        case ESCHER_AnchorMiddle:
+                            pValue = "middle";
+                        break;
+                        case ESCHER_AnchorBottom:
+                            pValue = "bottom";
+                        break;
+                        case ESCHER_AnchorTopCentered:
+                            pValue = "top-center";
+                        break;
+                        case ESCHER_AnchorMiddleCentered:
+                            pValue = "middle-center";
+                        break;
+                        case ESCHER_AnchorBottomCentered:
+                            pValue = "bottom-center";
+                        break;
+                        case ESCHER_AnchorTopBaseline:
+                            pValue = "top-baseline";
+                        break;
+                        case ESCHER_AnchorBottomBaseline:
+                            pValue = "bottom-baseline";
+                        break;
+                        case ESCHER_AnchorTopCenteredBaseline:
+                            pValue = "top-center-baseline";
+                        break;
+                        case ESCHER_AnchorBottomCenteredBaseline:
+                            pValue = "bottom-center-baseline";
+                        break;
+                    }
+                    m_ShapeStyle.append(";v-text-anchor:");
+                    m_ShapeStyle.append(pValue);
+                }
+                break;
+
             case ESCHER_Prop_txflTextFlow: // 136
                 {
                     // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 6bc298fa559a..3218ca060469 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -65,7 +65,9 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
     // text wrap -> VML
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
-
+    // vertical alignment -> VML
+    OUString const style = getXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape", "style");
+    CPPUNIT_ASSERT(style.indexOf("v-text-anchor:middle") != -1);
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit bca79d0e57a9c9bb3474668147310f7d642465ec
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:45:25 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:51:00 2020 +0200

    oox: VML export: produce bottom-to-top in a better way
    
    Replace code added in 090c61eb93db4302d4565d5f11f7673190835fdb
    with something that uses the already generated ESCHER property; this
    lets a warning about the unhandled property disappear too.
    
    Change-Id: Ieed83dd8e17e92eea9901124fce5e6da2a17196a

diff --git a/include/oox/export/vmlexport.hxx b/include/oox/export/vmlexport.hxx
index 83b5b91c0d41..7c2d3a62da6f 100644
--- a/include/oox/export/vmlexport.hxx
+++ b/include/oox/export/vmlexport.hxx
@@ -99,6 +99,9 @@ class OOX_DLLPUBLIC VMLExport : public EscherEx
     /// Remember style, the most important shape attribute ;-)
     OStringBuffer m_ShapeStyle;
 
+    /// style for textbox
+    OStringBuffer m_TextboxStyle;
+
     /// Remember the generated shape id.
     OString m_sShapeId;
 
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 6fcc83a66da6..555796c47a9c 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -430,6 +430,28 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const tools::Rectangle&
                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
                 break;
 
+            case ESCHER_Prop_txflTextFlow: // 136
+                {
+                    // at least "bottom-to-top" only has an effect when it's on the v:textbox element, not on v:shape
+                    assert(m_TextboxStyle.isEmpty());
+                    switch (opt.nPropValue)
+                    {
+                        case ESCHER_txflHorzN:
+                            m_TextboxStyle.append("layout-flow:horizontal");
+                        break;
+                        case ESCHER_txflTtoBA:
+                            m_TextboxStyle.append("layout-flow:vertical");
+                        break;
+                        case ESCHER_txflBtoT:
+                            m_TextboxStyle.append("mso-layout-flow-alt:bottom-to-top");
+                        break;
+                        default:
+                            assert(false); // unimplemented in escher export
+                        break;
+                    }
+                }
+                break;
+
             // coordorigin
             case ESCHER_Prop_geoLeft: // 320
             case ESCHER_Prop_geoTop: // 321
@@ -1345,6 +1367,8 @@ sal_Int32 VMLExport::StartShape()
     // start of the shape
     m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
 
+    OString const textboxStyle(m_TextboxStyle.makeStringAndClear());
+
     // now check if we have some editeng text (not associated textbox) and we have a text exporter registered
     const SdrTextObj* pTxtObj = dynamic_cast<const SdrTextObj*>( m_pSdrObject );
     if (pTxtObj && m_pTextExport && msfilter::util::HasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject))
@@ -1369,19 +1393,11 @@ sal_Int32 VMLExport::StartShape()
 
         if( pParaObj )
         {
-            uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
             sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
             sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
-            if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+            if (!textboxStyle.isEmpty())
             {
-                sal_Int32 nTextRotateAngle = sal_Int32();
-                if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
-                {
-                    if (nTextRotateAngle == 9000)
-                    {
-                        pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
-                    }
-                }
+                pTextboxAttrList->add(XML_style, textboxStyle);
             }
 
             // this is reached only in case some text is attached to the shape
commit 86282cea5003579a82585a8e7e7dc5fe783db5c0
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 15:26:48 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:51:00 2020 +0200

    filter: MSO export: convert TextWrap property to Escher_Wrap*
    
    There's a paucity of working wrapping modes in Escher unfortunately.
    
    Change-Id: Ibaf99c3249a6492dc129f9c9b5707778038f9a4c

diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index f04043e9156a..a2071237deb7 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -66,6 +66,7 @@
 #include <com/sun/star/drawing/FlagSequence.hpp>
 #include <com/sun/star/drawing/PolygonFlags.hpp>
 #include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
@@ -699,6 +700,10 @@ void EscherPropertyContainer::CreateTextProperties(
     bool bWordWrap          ( false );
     bool bAutoGrowSize      ( false );
 
+    uno::Any aTextWrap;
+
+    EscherPropertyValueHelper::GetPropertyValue(aTextWrap, rXPropSet, "TextWrap", true);
+
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
         aAny >>= eWM;
     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
@@ -837,6 +842,21 @@ void EscherPropertyContainer::CreateTextProperties(
                 nTextAttr |= 0x20002;
         }
     }
+
+    if (aTextWrap.hasValue())
+    {   // explicit text wrap overrides whatever was inferred previously
+        switch (aTextWrap.get<text::WrapTextMode>())
+        {
+            case text::WrapTextMode_THROUGH:
+                eWrapMode = ESCHER_WrapNone;
+                break;
+            // in theory there are 3 more Escher_Wrap, but [MS-ODRAW] says they are useless
+            default:
+                eWrapMode = ESCHER_WrapSquare;
+                break;
+        }
+    }
+
     AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
     AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
     AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 51e4c6b63b96..6bc298fa559a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -63,6 +63,8 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
 
     // now test text rotation -> VML writing direction
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+    // text wrap -> VML
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/w10:wrap", "type", "none");
 
 }
 
commit 08301ac462a200ab89124f1d2e36f220f88c4661
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 7 16:41:18 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:51:00 2020 +0200

    sw: register w10 prefix
    
    Change-Id: I1ca9c3c7c4f36b666ee7d17967b80fdaa7004874

diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx
index 38f8e95a4a40..d62b92b58fc0 100644
--- a/sw/qa/inc/swmodeltestbase.hxx
+++ b/sw/qa/inc/swmodeltestbase.hxx
@@ -962,6 +962,7 @@ protected:
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office"));
+        xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w10"), BAD_CAST("urn:schemas-microsoft-com:office:word"));
         // odt
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("style"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:style:1.0"));
commit 086e0e4a211a564122f527e329fede2a8e315cdc
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 6 14:11:38 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:50:59 2020 +0200

    oox: VML export: for rotated text shape, produce bottom-to-top
    
    This is for shapes that fail the lcl_isTextBox() check in
    VMLExport::StartShape(), they can be rotated too but with a different
    property than the "TextPreRotateAngle" that is used in
    VMLExport::EndShape().
    
    Change-Id: I530aae8b7138f47bae8434e205632f5f4adbb231
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100249
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 090c61eb93db4302d4565d5f11f7673190835fdb)

diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 98f3243e5461..6fcc83a66da6 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -1369,8 +1369,23 @@ sal_Int32 VMLExport::StartShape()
 
         if( pParaObj )
         {
+            uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
+            sax_fastparser::FastAttributeList* pTextboxAttrList = FastSerializerHelper::createAttrList();
+            sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
+            if (xPropertySet->getPropertySetInfo()->hasPropertyByName("RotateAngle"))
+            {
+                sal_Int32 nTextRotateAngle = sal_Int32();
+                if (xPropertySet->getPropertyValue("RotateAngle") >>= nTextRotateAngle)
+                {
+                    if (nTextRotateAngle == 9000)
+                    {
+                        pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
+                    }
+                }
+            }
+
             // this is reached only in case some text is attached to the shape
-            m_pSerializer->startElementNS(XML_v, XML_textbox);
+            m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
             m_pTextExport->WriteOutliner(*pParaObj);
             m_pSerializer->endElementNS(XML_v, XML_textbox);
             if( bOwnParaObj )
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index 634215adab08..51e4c6b63b96 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -60,6 +60,10 @@ DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
         "/wp:positionV/wp:posOffset", "1080135");
     assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
         "/wp:positionV", "relativeFrom", "page");
+
+    // now test text rotation -> VML writing direction
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Fallback/w:pict/v:shape/v:textbox", "style", "mso-layout-flow-alt:bottom-to-top");
+
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit c405fd0c1ba2358bc55b7ee5ec7c8b7df49de2a8
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 19:09:38 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:50:59 2020 +0200

    tdf#135464 sw: avoid invalid combinations of HoriOrientRelation and FLY_AT_PAGE
    
    ... when using Anchor->To Page context menu.
    
    For shapes, in SwDoc::ChgAnchor() and for sw flys in
    SwDoc::SetFlyFrameAnchor().
    
    Change-Id: I7d747b2558ef69df99636ea0fb0409deb461a79a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100131
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 1de2b0d3234462b488db54d36ebc17e2b579b0f0)

diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 4451115905a8..cc3b858028c2 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -372,6 +372,7 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
                 pItem = nullptr;
 
             SwFormatHoriOrient aOldH( rFormat.GetHoriOrient() );
+            bool bPutOldH(false);
 
             if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
                 aOldH.GetPos() == static_cast<const SwFormatHoriOrient*>(pItem)->GetPos() ))
@@ -386,6 +387,22 @@ sal_Int8 SwDoc::SetFlyFrameAnchor( SwFrameFormat& rFormat, SfxItemSet& rSet, boo
                     aOldH.SetRelationOrient( pH->GetRelationOrient() );
                 }
                 aOldH.SetPos( nPos );
+                bPutOldH = true;
+            }
+            if (nNew == RndStdIds::FLY_AT_PAGE)
+            {
+                sal_Int16 nRelOrient(pItem
+                    ? static_cast<const SwFormatHoriOrient*>(pItem)->GetRelationOrient()
+                    : aOldH.GetRelationOrient());
+                if (sw::GetAtPageRelOrientation(nRelOrient, false))
+                {
+                    SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+                    aOldH.SetRelationOrient(nRelOrient);
+                    bPutOldH = true;
+                }
+            }
+            if (bPutOldH)
+            {
                 rSet.Put( aOldH );
             }
 
@@ -915,6 +932,17 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
                 // of attributes (method call <SetAttr(..)>) takes care of the
                 // invalidation of the object position.
                 SetAttr( aNewAnch, *pContact->GetFormat() );
+                if (aNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+                {
+                    SwFormatHoriOrient item(pContact->GetFormat()->GetHoriOrient());
+                    sal_Int16 nRelOrient(item.GetRelationOrient());
+                    if (sw::GetAtPageRelOrientation(nRelOrient, false))
+                    {
+                        SAL_INFO("sw.ui", "fixing horizontal RelOrientation for at-page anchor");
+                        item.SetRelationOrient(text::RelOrientation::PAGE_FRAME);
+                        SetAttr(item, *pContact->GetFormat());
+                    }
+                }
                 if ( _bPosCorr )
                 {
                     // #i33313# - consider not connected 'virtual' drawing
diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
index 079468fdf062..f3813192c928 100644
--- a/sw/source/core/layout/anchoreddrawobject.cxx
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -719,7 +719,10 @@ void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrame* _pNewAnchorFram
         nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
     }
 
-    GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+    GetFrameFormat().SetFormatAttr( SwFormatHoriOrient( nHoriRelPos, text::HoriOrientation::NONE,
+        GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE
+            ? text::RelOrientation::PAGE_FRAME
+            : text::RelOrientation::FRAME ) );
     GetFrameFormat().SetFormatAttr( SwFormatVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
 }
 
commit b8c028f8a471ed30f409b51c5765fbb91b5ef22c
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 4 18:56:08 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:50:59 2020 +0200

    tdf#135464 sw: ODT->DOCX: fix positioning of at-page shapes and frames
    
    Exporting at-page anchored flys to DOCX can result in wrong positions,
    because DocxSdrExport::startDMLAnchorInline() converts
    text::RelOrientation::FRAME to relativeFrom="column", i.e. the margin,
    but sw displays it as relative to the page.
    
    In fact at-page and FRAME is an invalid combination according to the
    table in ODF 1.3, 20.298 style:horizontal-pos, the paragraph and
    character relations are not valid for page-anchored flys.
    
    Since there are lots of ODT files with this invalid combination, try to
    fix it on import, in SwXFrame and SwXShape.
    
    Funnily, SwXShape is attached before the properties are set, while
    SwXFrame is attached after the properties are set.
    
    The anchor frame for at-page is always a SwPageFrame.
    
    Unfortunately there is a case where PRINT_AREA and PAGE_PRINT_AREA
    differ, namely the CalcClipRect() only handles PRINT_AREA so it will
    crop to the right margin with that but not with PAGE_PRINT_AREA,
    so don't map this value.
    
    Change-Id: I4d5f7f87d045ac4539b9170e55c34d4afe801f4d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100130
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 12645900dece0a9aa0661fee796c27f672217977)

diff --git a/sw/inc/fmtornt.hxx b/sw/inc/fmtornt.hxx
index 24ffdc907e26..d0bea643f980 100644
--- a/sw/inc/fmtornt.hxx
+++ b/sw/inc/fmtornt.hxx
@@ -108,6 +108,12 @@ inline const SwFormatVertOrient &SwFormat::GetVertOrient(bool bInP) const
 inline const SwFormatHoriOrient &SwFormat::GetHoriOrient(bool bInP) const
     { return m_aSet.GetHoriOrient(bInP); }
 
+namespace sw {
+
+    bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea);
+
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
new file mode 100644
index 000000000000..fce84f93e945
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/rotated_shape.fodt
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:officeooo="http://openoffice.org/2009/office" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rpt="http://openoffice.org/2005/report" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns
 :config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur
 n:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>
+  <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
+  <style:font-face style:name="Lucida Sans" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+  <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+  <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+  <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph">
+   <style:paragraph-properties style:writing-mode="lr-tb"/>
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph">
+   <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+   <style:paragraph-properties style:writing-mode="lr-tb"/>
+   <style:text-properties fo:font-size="11pt"/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Arial" fo:font-size="7pt" fo:language="de" fo:country="DE" style:font-name-asian="Times New Roman" style:font-size-asian="7pt" style:font-name-complex="Arial" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/>
+  </style:style>
+  <style:style style:name="gr1" style:family="graphic">
+   <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" draw:auto-grow-width="false" fo:padding-top="0.254cm" fo:padding-bottom="0.254cm" fo:padding-left="0.127cm" fo:padding-right="0.127cm" fo:wrap-option="wrap" draw:shadow="hidden" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="page" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/>
+   <style:paragraph-properties style:writing-mode="lr-tb"/>
+  </style:style>
+  <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
+   <style:graphic-properties style:horizontal-pos="from-left" style:horizontal-rel="paragraph" style:vertical-pos="from-top" style:vertical-rel="page" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
+    <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <draw:frame text:anchor-type="page" text:anchor-page-number="1" draw:z-index="0" draw:name="Shape1" draw:style-name="gr1" draw:text-style-name="P2" svg:width="5.896cm" svg:height="0.957cm" draw:transform="rotate (1.5707963267949) translate (1.13418055555556cm 26.0579305555556cm)">
+    <draw:text-box>
+     <text:p text:style-name="P1"><text:span text:style-name="T1"><text:s/></text:span><text:span text:style-name="T1">Foo</text:span></text:p>
+    </draw:text-box>
+   </draw:frame><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="page" text:anchor-page-number="1" svg:width="0.67cm" svg:height="0.67cm" draw:z-index="0"><draw:image draw:mime-type="image/png" svg:x="2cm" svg:y="3cm">
+     <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAAXNSR0IArs4c6QAAAAZiS0dE
+      AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJBhI0A6HXrrIAAABl
+      SURBVDjLY/z//z8DtQATMYokl7D8p4phMIOIMZCJFBcRMpCJVK/hM5CJnDDCJc9EbmBjU8dE
+      jkG41DPhM+h5zB9GfHx0fTgjAJtGfOIMDAwMLMQoItZAJgYqglHDhpNhjNQsaQHF4y3hS/bS
+      HgAAAABJRU5ErkJggg==
+     </office:binary-data>
+    </draw:image>
+   </draw:frame>
+   <text:p text:style-name="Standard"/>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
index dedad4d00eab..634215adab08 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport15.cxx
@@ -33,6 +33,35 @@ DECLARE_OOXMLEXPORT_TEST(testTdf133334_followPgStyle, "tdf133334_followPgStyle.o
     CPPUNIT_ASSERT_EQUAL(2, getPages());
 }
 
+DECLARE_OOXMLEXPORT_TEST(testAtPageShapeRelOrientation, "rotated_shape.fodt")
+{
+    // invalid combination of at-page anchor and horizontal-rel="paragraph"
+    // caused relativeFrom="column" instead of relativeFrom="page"
+
+    xmlDocPtr pXmlDocument = parseExport("word/document.xml");
+    if (!pXmlDocument)
+        return;
+
+    assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
+        "/wp:positionH/wp:posOffset", "-480060");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
+        "/wp:positionH", "relativeFrom", "page");
+    assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
+        "/wp:positionV/wp:posOffset", "8147685");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor"
+        "/wp:positionV", "relativeFrom", "page");
+
+    // same for sw
+    assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
+        "/wp:positionH/wp:posOffset", "720090");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
+        "/wp:positionH", "relativeFrom", "page");
+    assertXPathContent(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
+        "/wp:positionV/wp:posOffset", "1080135");
+    assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:drawing/wp:anchor"
+        "/wp:positionV", "relativeFrom", "page");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 79235781896d..18700e9b2eb4 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -98,6 +98,39 @@
 using namespace ::com::sun::star;
 
 
+namespace sw {
+
+bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintArea)
+{
+    switch (rOrientation)
+    {
+        case text::RelOrientation::CHAR:
+        case text::RelOrientation::FRAME:
+            rOrientation = text::RelOrientation::PAGE_FRAME;
+            return true;
+        case text::RelOrientation::PRINT_AREA:
+            if (isIgnorePrintArea)
+            {
+                return false;
+            }
+            else
+            {
+                rOrientation = text::RelOrientation::PAGE_PRINT_AREA;
+                return true;
+            }
+        case text::RelOrientation::FRAME_LEFT:
+            rOrientation = text::RelOrientation::PAGE_LEFT;
+            return true;
+        case text::RelOrientation::FRAME_RIGHT:
+            rOrientation = text::RelOrientation::PAGE_RIGHT;
+            return true;
+        default:
+            return false;
+    }
+}
+
+} // namespace sw
+
 SfxPoolItem* SwFormatLineNumber::CreateDefault() { return new SwFormatLineNumber; }
 
 static sal_Int16 lcl_IntToRelation(const uno::Any& rVal)
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
index a94255c55408..d1b058fa49a2 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -1227,6 +1227,21 @@ void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& a
                         }
                     }
                 }
+                else if (pEntry->nWID == RES_HORI_ORIENT
+                    && pEntry->nMemberId == MID_HORIORIENT_RELATION
+                    && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+                {
+                    uno::Any value(aValue);
+                    sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME);
+                    aValue >>= nRelOrient;
+                    if (sw::GetAtPageRelOrientation(nRelOrient, true))
+                    {
+                        SAL_WARN("sw.core", "SwXShape: fixing invalid horizontal RelOrientation for at-page anchor");
+                        value <<= nRelOrient;
+                    }
+                    m_pPropSet->setPropertyValue( *pEntry, value, aSet );
+                    pFormat->SetFormatAttr(aSet);
+                }
                 else
                 {
                     m_pPropSet->setPropertyValue( *pEntry, aValue, aSet );
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index e2e5c9411715..0636d530662c 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -2749,6 +2749,19 @@ void SwXFrame::attachToRange(uno::Reference<text::XTextRange> const& xTextRange,
             aAnchor.SetAnchor( aPam.GetPoint() );
             aFrameSet.Put(aAnchor);
         }
+
+        if (eAnchorId == RndStdIds::FLY_AT_PAGE)
+        {
+            sal_Int16 nRelOrient(aFrameSet.Get(RES_HORI_ORIENT).GetRelationOrient());
+            if (sw::GetAtPageRelOrientation(nRelOrient, true))
+            {
+                SAL_WARN("sw.core", "SwXFrame: fixing invalid horizontal RelOrientation for at-page anchor");
+
+                SwFormatHoriOrient item(aFrameSet.Get(RES_HORI_ORIENT));
+                item.SetRelationOrient(nRelOrient);
+                aFrameSet.Put(item);
+            }
+        }
     }
 
     const ::uno::Any* pStyle;
commit 393151fac4563d95056016a60260d30656e2b988
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Apr 14 17:42:06 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:50:58 2020 +0200

    sw: DOCX export: export AddExternalLeading as w:noLeading
    
    For 11pt Arial, can fit 59 paragraphs on a page vs. 57...
    
    This is annoyingly complicated by the fact that Word 2013 ignores
    w:noLeading element if compatibilityMode is 15.
    
    Change-Id: Ie3093eabba45cdf6e7903ed860f5bad24dcc0323
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92208
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 968a7e3247169489d29cc7de0079eea12a663870)
    
    For the backport, don't care about compatibilityMode, it won't be in
    grab-bag on ODF import so rely on the default of 12.
    
    Change-Id: Ia41d6a4c99ebcc364997d0bb565addf7dc546ced

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index c368e6682833..c03d971e8fdc 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3695,6 +3695,7 @@ sal_Int32 lcl_getWordCompatibilityMode( const SwDoc& rDoc )
     uno::Reference< beans::XPropertySet >     xPropSet( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
     uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
 
+    sal_Int32 nWordCompatibilityMode = -1;
     if ( xPropSetInfo->hasPropertyByName( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) )
     {
         uno::Sequence< beans::PropertyValue > propList;
@@ -3725,14 +3726,14 @@ sal_Int32 lcl_getWordCompatibilityMode( const SwDoc& rDoc )
 
                     if ( sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word" )
                     {
-                        return sVal.toInt32();
+                        nWordCompatibilityMode = sVal.toInt32();
                     }
                 }
             }
         }
     }
 
-    return -1; // Word compatibility mode not found
+    return nWordCompatibilityMode;
 }
 
 }
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 7fed578100d1..a212f4e5c9b8 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -895,6 +895,21 @@ void DocxExport::WriteProperties( )
     m_pFilter->exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly );
 }
 
+static auto
+WriteCompat(SwDoc const& rDoc, ::sax_fastparser::FSHelperPtr const& rpFS
+        ) -> void
+{
+    if (!rDoc.getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING))
+    {
+        rpFS->singleElementNS(XML_w, XML_noLeading);
+    }
+    // Do not justify lines with manual break
+    if (rDoc.getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK))
+    {
+        rpFS->singleElementNS(XML_w, XML_doNotExpandShiftReturn);
+    }
+}
+
 void DocxExport::WriteSettings()
 {
     SwViewShell *pViewShell(m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell());
@@ -978,14 +993,6 @@ void DocxExport::WriteSettings()
         pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
             OString::number(m_aSettings.defaultTabStop) );
 
-    // Do not justify lines with manual break
-    if( m_pDoc->getIDocumentSettingAccess().get( DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK ))
-    {
-        pFS->startElementNS(XML_w, XML_compat);
-        pFS->singleElementNS(XML_w, XML_doNotExpandShiftReturn);
-        pFS->endElementNS( XML_w, XML_compat );
-    }
-
     // export current mail merge database and table names
     SwDBData aData = m_pDoc->GetDBData();
     if ( !aData.sDataSource.isEmpty() && aData.nCommandType == css::sdb::CommandType::TABLE && !aData.sCommand.isEmpty() )
@@ -1046,6 +1053,7 @@ void DocxExport::WriteSettings()
         bHasDummyRedlineProtectionKey = aKey.getLength() == 1 && aKey[0] == 1;
     }
     const OUString aGrabBagName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
+    bool bHasCompat = false;
     if ( xPropSetInfo->hasPropertyByName( aGrabBagName ) )
     {
         uno::Sequence< beans::PropertyValue > propList;
@@ -1076,6 +1084,10 @@ void DocxExport::WriteSettings()
             {
                 pFS->startElementNS(XML_w, XML_compat);
 
+                WriteCompat(*m_pDoc, pFS);
+
+                bHasCompat = true;
+
                 uno::Sequence< beans::PropertyValue > aCompatSettingsSequence;
                 rProp.Value >>= aCompatSettingsSequence;
 
@@ -1161,6 +1173,14 @@ void DocxExport::WriteSettings()
             }
         }
     }
+    if (!bHasCompat)
+    {
+        pFS->startElementNS(XML_w, XML_compat);
+
+        WriteCompat(*m_pDoc, pFS);
+
+        pFS->endElementNS( XML_w, XML_compat );
+    }
 
     if (! hasProtectionProperties)
     {
commit 1f085e4c9bc7d6c269bde06bfef33b2e314dd9d2
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Apr 14 18:10:53 2020 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 13 15:50:58 2020 +0200

    writerfilter: DOCX import: import w:noLeading as AddExternalLeading
    
    Change-Id: I3d7fa2984975205d284575c60c6c47284b00c4a0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92209
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 3cd3ae30217a80449799d7d9426c3756c572712e)

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 3b95e006ffad..288c18b83fd4 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -6610,6 +6610,10 @@ void DomainMapper_Impl::ApplySettingsTable()
             if( m_pSettingsTable->GetEmbedSystemFonts())
                 xSettings->setPropertyValue( getPropertyName( PROP_EMBED_SYSTEM_FONTS ), uno::makeAny(true) );
             xSettings->setPropertyValue("AddParaTableSpacing", uno::makeAny(m_pSettingsTable->GetDoNotUseHTMLParagraphAutoSpacing()));
+            if (m_pSettingsTable->GetNoLeading())
+            {
+                xSettings->setPropertyValue("AddExternalLeading", uno::makeAny(!m_pSettingsTable->GetNoLeading()));
+            }
             if( m_pSettingsTable->GetProtectForm() )
                 xSettings->setPropertyValue("ProtectForm", uno::makeAny( true ));
         }
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index 90fb9c98752d..87b4871ca9b6 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -256,6 +256,7 @@ struct SettingsTable_Impl
     bool                m_bRedlineProtection;
     OUString            m_sRedlineProtectionKey;
     bool                m_bDisplayBackgroundShape;
+    bool                m_bNoLeading = false;
 
     uno::Sequence<beans::PropertyValue> m_pThemeFontLangProps;
 
@@ -571,6 +572,9 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
     case NS_ooxml::LN_CT_Settings_displayBackgroundShape:
         m_pImpl->m_bDisplayBackgroundShape = nIntValue;
         break;
+    case NS_ooxml::LN_CT_Compat_noLeading:
+        m_pImpl->m_bNoLeading = nIntValue != 0;
+        break;
     default:
     {
 #ifdef DBG_UTIL
@@ -795,6 +799,11 @@ bool SettingsTable::GetLongerSpaceSequence() const
     return m_pImpl->m_bLongerSpaceSequence;
 }
 
+bool SettingsTable::GetNoLeading() const
+{
+    return m_pImpl->m_bNoLeading;
+}
+
 }//namespace dmapper
 } //namespace writerfilter
 
diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx
index 26c69d907b35..7f8cc8ba9bc4 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -78,6 +78,7 @@ class SettingsTable : public LoggedProperties, public LoggedTable
     bool GetNoColumnBalance() const;
     bool GetProtectForm() const;
     bool GetLongerSpaceSequence() const;
+    bool GetNoLeading() const;
     bool GetNoHyphenateCaps() const;
     sal_Int16 GetHypenationZone() const;
 
commit ed79b0f274c913ce8206a68a2ca9296b84ac0751
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Thu Jun 11 09:45:03 2020 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Thu Aug 13 11:13:49 2020 +0200

    tdf#128197: sw: different line height for DOCX with compat=14
    
    Lines containing just a shape inline without any other text are
    treated in DOCX with compatibility option 15 and 14 in a different
    way: while compat=15 is layouting line exatly as LO does, in
    compat=14 mode minimal line height takes into account just shape
    height and not current font.
    
    Change-Id: Id2bdab941a0bbaa9080567d736435d9e0babd490
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96080
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100542

diff --git a/sw/inc/IDocumentSettingAccess.hxx b/sw/inc/IDocumentSettingAccess.hxx
index f182027ded95..814f139b64fc 100644
--- a/sw/inc/IDocumentSettingAccess.hxx
+++ b/sw/inc/IDocumentSettingAccess.hxx
@@ -63,7 +63,8 @@ enum class DocumentSettingId
 
     // tdf#104349 tdf#104668
     MS_WORD_COMP_TRAILING_BLANKS,
-
+    // tdf#128197 MS Word in some modes can have line height based on shape height, not on font
+    MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY,
     UNIX_FORCE_ZERO_EXT_LEADING,
     TABS_RELATIVE_TO_INDENT,
     PROTECT_FORM,
diff --git a/sw/qa/extras/ooxmlexport/data/128197_compat14.docx b/sw/qa/extras/ooxmlexport/data/128197_compat14.docx
new file mode 100644
index 000000000000..507e28396019
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/128197_compat14.docx differ
diff --git a/sw/qa/extras/ooxmlexport/data/128197_compat15.docx b/sw/qa/extras/ooxmlexport/data/128197_compat15.docx
new file mode 100644
index 000000000000..d618b117cfec
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/128197_compat15.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
index 237e19092d1a..18a22bbdd30c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
@@ -35,6 +35,21 @@ protected:
     }
 };
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf128197)
+{
+    load(mpTestDocumentPath, "128197_compat14.docx");
+    xmlDocPtr pLayout14 = parseLayoutDump();
+    sal_Int32 nHeight14 = getXPath(pLayout14, "//page[1]/body/txt[1]/infos/bounds", "height").toInt32();
+
+    load(mpTestDocumentPath, "128197_compat15.docx");
+    xmlDocPtr pLayout15 = parseLayoutDump();
+    sal_Int32 nHeight15 = getXPath(pLayout15, "//page[1]/body/txt[1]/infos/bounds", "height").toInt32();
+
+    // In compat mode=14 second line has size of the shape thus entire paragraph height is smaller
+    // So nHeight14 < nHeight15
+    CPPUNIT_ASSERT_LESS(nHeight15, nHeight14);
+}
+
 DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf78749, "tdf78749.docx")
 {
     //Shape lost the background image before, now check if it still has...
diff --git a/sw/source/core/doc/DocumentSettingManager.cxx b/sw/source/core/doc/DocumentSettingManager.cxx
index 11210614c56f..b7f3af73d2af 100644
--- a/sw/source/core/doc/DocumentSettingManager.cxx
+++ b/sw/source/core/doc/DocumentSettingManager.cxx
@@ -76,6 +76,7 @@ sw::DocumentSettingManager::DocumentSettingManager(SwDoc &rDoc)
     mbTabRelativeToIndent(true),
     mbProtectForm(false), // i#78591#
     mbMsWordCompTrailingBlanks(false), // tdf#104349 tdf#104668
+    mbMsWordCompMinLineHeightByFly(false),
     mbInvertBorderSpacing (false),
     mbCollapseEmptyCellPara(true),
     mbTabAtLeftIndentForParagraphsInList(false), //#i89181#
@@ -181,6 +182,7 @@ bool sw::DocumentSettingManager::get(/*[in]*/ DocumentSettingId id) const
         case DocumentSettingId::PROTECT_FORM: return mbProtectForm;
         // tdf#104349 tdf#104668
         case DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS: return mbMsWordCompTrailingBlanks;
+        case DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: return mbMsWordCompMinLineHeightByFly;
         // #i89181#
         case DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList;
         case DocumentSettingId::INVERT_BORDER_SPACING: return mbInvertBorderSpacing;
@@ -327,6 +329,10 @@ void sw::DocumentSettingManager::set(/*[in]*/ DocumentSettingId id, /*[in]*/ boo
             mbMsWordCompTrailingBlanks = value;
             break;
 
+        case DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY:
+            mbMsWordCompMinLineHeightByFly = value;
+            break;
+
         case DocumentSettingId::TABS_RELATIVE_TO_INDENT:
             mbTabRelativeToIndent = value;
             break;
@@ -597,6 +603,7 @@ void sw::DocumentSettingManager::ReplaceCompatibilityOptions(const DocumentSetti
     mbClipAsCharacterAnchoredWriterFlyFrames = rSource.mbClipAsCharacterAnchoredWriterFlyFrames;
     mbUnixForceZeroExtLeading = rSource.mbUnixForceZeroExtLeading;
     mbTabRelativeToIndent = rSource.mbTabRelativeToIndent;
+    mbMsWordCompMinLineHeightByFly = rSource.mbMsWordCompMinLineHeightByFly;
     mbTabAtLeftIndentForParagraphsInList = rSource.mbTabAtLeftIndentForParagraphsInList;
     mbSubtractFlys = rSource.mbSubtractFlys;
     mbMsWordCompTrailingBlanks = rSource.mbMsWordCompTrailingBlanks;
diff --git a/sw/source/core/inc/DocumentSettingManager.hxx b/sw/source/core/inc/DocumentSettingManager.hxx
index fe87b339307c..e548c55a26b2 100644
--- a/sw/source/core/inc/DocumentSettingManager.hxx
+++ b/sw/source/core/inc/DocumentSettingManager.hxx
@@ -142,6 +142,7 @@ class DocumentSettingManager :
     bool mbTabRelativeToIndent                      : 1;   // #i24363# tab stops relative to indent
     bool mbProtectForm                              : 1;
     bool mbMsWordCompTrailingBlanks                 : 1;   // tdf#104349 tdf#104668
+    bool mbMsWordCompMinLineHeightByFly             : 1;
     bool mbInvertBorderSpacing                      : 1;
     bool mbCollapseEmptyCellPara                    : 1;
     bool mbTabAtLeftIndentForParagraphsInList;             // #i89181# - see above
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 89c7641df414..4e57a0b64d90 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -333,6 +333,16 @@ void SwTextFormatter::InsertPortion( SwTextFormatInfo &rInf,
             m_pCurr->Height( pPor->Height() );
         if( m_pCurr->GetAscent() < pPor->GetAscent() )
             m_pCurr->SetAscent( pPor->GetAscent() );
+
+        if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY))
+        {
+            // For DOCX with compat=14 the only shape in line defines height of the line inspite of used font
+            if (pLast->IsFlyCntPortion() && pPor->IsTextPortion() && pPor->GetLen() == TextFrameIndex(0))
+            {
+                m_pCurr->SetAscent(pLast->GetAscent());
+                m_pCurr->Height(pLast->Height());
+            }
+        }
     }
 
     // Sometimes chains are constructed (e.g. by hyphenate)
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx
index 9887cdc11dc8..51124bfe4071 100644
--- a/sw/source/uibase/uno/SwXDocumentSettings.cxx
+++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx
@@ -114,6 +114,7 @@ enum SwDocumentSettingsPropertyHandles
     HANDLE_USE_OLD_PRINTER_METRICS,
     HANDLE_PROTECT_FORM,
     HANDLE_MS_WORD_COMP_TRAILING_BLANKS,
+    HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY,
     HANDLE_TABS_RELATIVE_TO_INDENT,
     HANDLE_RSID,
     HANDLE_RSID_ROOT,
@@ -203,6 +204,7 @@ static MasterPropertySetInfo * lcl_createSettingsInfo()
         { OUString("RsidRoot"), HANDLE_RSID_ROOT, cppu::UnoType<sal_Int32>::get(), 0},
         { OUString("ProtectForm"), HANDLE_PROTECT_FORM, cppu::UnoType<bool>::get(), 0},
         { OUString("MsWordCompTrailingBlanks"), HANDLE_MS_WORD_COMP_TRAILING_BLANKS, cppu::UnoType<bool>::get(), 0 },
+        { OUString("MsWordCompMinLineHeightByFly"), HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, cppu::UnoType<bool>::get(), 0 },
         { OUString("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, cppu::UnoType<bool>::get(), 0},
         { OUString("ModifyPasswordInfo"), HANDLE_MODIFYPASSWORDINFO, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), 0},
         { OUString("MathBaselineAlignment"), HANDLE_MATH_BASELINE_ALIGNMENT, cppu::UnoType<bool>::get(), 0},
@@ -749,6 +751,12 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf
             mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, bTmp);
         }
         break;
+        case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY:
+        {
+            bool bTmp = *o3tl::doAccess<bool>(rValue);
+            mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, bTmp);
+        }
+        break;
         case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
         {
             bool bTmp = *o3tl::doAccess<bool>(rValue);
@@ -1275,6 +1283,11 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf
             rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS);
         }
         break;
+        case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY:
+        {
+            rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY);
+        }
+        break;
         case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
         {
             rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index 58399cf0a151..90fb9c98752d 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -23,6 +23,7 @@
 
 #include <rtl/ustring.hxx>
 #include <sfx2/zoomitem.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/beans/XPropertyState.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
@@ -701,6 +702,13 @@ void SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& x
 {
     uno::Reference< beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY );
 
+    if (GetWordCompatibilityMode() <= 14)
+    {
+        uno::Reference<lang::XMultiServiceFactory> xTextFactory(xDoc, uno::UNO_QUERY_THROW);
+        uno::Reference<beans::XPropertySet> xDocumentSettings(xTextFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW);
+        xDocumentSettings->setPropertyValue("MsWordCompMinLineHeightByFly", uno::makeAny(true));
+    }
+
     // Show changes value
     if (xDocProps.is())
     {
commit f27fd86d2dc424cee2d28fe77d881eacc4795eaf
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Aug 11 15:29:38 2020 +0100
Commit:     Xisco Fauli <xiscofauli at libreoffice.org>
CommitDate: Wed Aug 12 11:36:23 2020 +0200

    tdf#135442 min supported version of gtk3 is 3.18 not 3.20
    
    Change-Id: Iaa2eefbe08fad3a7dd6eff98bf5fb513053a263d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100541
    Tested-by: Xisco Fauli <xiscofauli at libreoffice.org>
    Reviewed-by: Xisco Fauli <xiscofauli at libreoffice.org>

diff --git a/sd/uiconfig/simpress/ui/clientboxfragment.ui b/sd/uiconfig/simpress/ui/clientboxfragment.ui
index 361caeeb4823..e5811360878d 100644
--- a/sd/uiconfig/simpress/ui/clientboxfragment.ui
+++ b/sd/uiconfig/simpress/ui/clientboxfragment.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.22.1 -->
 <interface domain="sd">
-  <requires lib="gtk+" version="3.20"/>
+  <requires lib="gtk+" version="3.18"/>
   <object class="GtkGrid" id="ClientboxFragment">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
diff --git a/vcl/uiconfig/ui/wizard.ui b/vcl/uiconfig/ui/wizard.ui
index e1f68da9e66a..76f92607f1ce 100644
--- a/vcl/uiconfig/ui/wizard.ui
+++ b/vcl/uiconfig/ui/wizard.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.22.1 -->
 <interface domain="vcl">
-  <requires lib="gtk+" version="3.20"/>
+  <requires lib="gtk+" version="3.18"/>
   <object class="GtkAssistant" id="Wizard">
     <property name="can_focus">True</property>
     <property name="border_width">6</property>
commit b6e41d97fa8ee9e265970325348a6be111978c2c
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Wed Jul 22 10:44:46 2020 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Aug 12 09:19:43 2020 +0200

    tdf#134043 DOCX import: new unit tests: ComboBox to DropDown
    
    Change-Id: I034b0cd9c6f66c531460d1bb69d9ede5ff46f7d7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97531
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99994
    
    tdf#134572 DOCX: Incorrect default value in dropdown text fields
    
    Change-Id: I3169e817c2f033d1525adc3b02ac3680ad220d70
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99074
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100306

diff --git a/sw/CppunitTest_sw_ooxmlexport4.mk b/sw/CppunitTest_sw_ooxmlexport4.mk
index e3285932e004..0f026bc8384e 100644
--- a/sw/CppunitTest_sw_ooxmlexport4.mk
+++ b/sw/CppunitTest_sw_ooxmlexport4.mk
@@ -11,4 +11,8 @@
 
 $(eval $(call sw_ooxmlexport_test,4))
 
+$(eval $(call gb_CppunitTest_use_custom_headers,sw_ooxmlexport4,\
+    officecfg/registry \
+))
+
 # vim: set noet sw=4 ts=4:
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index abb55384f68f..5ad0a4ece74c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -900,7 +900,7 @@ DECLARE_OOXMLEXPORT_TEST(tdf119809, "tdf119809.docx")
         CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown"));
 
         uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items");
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aItems.getLength());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aItems.getLength());
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
index c80c8f6655bb..c39c7d747b83 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
@@ -23,6 +23,9 @@
 #include <com/sun/star/util/Date.hpp>
 #include <unotools/tempfile.hxx>
 #include <config_features.h>
+#include <comphelper/configuration.hxx>
+#include <officecfg/Office/Writer.hxx>
+
 
 class Test : public SwModelTestBase
 {
@@ -43,6 +46,19 @@ protected:
         // If the testcase is stored in some other format, it's pointless to test.
         return (OString(filename).endsWith(".docx") && std::find(vBlacklist.begin(), vBlacklist.end(), filename) == vBlacklist.end());
     }
+
+    virtual std::unique_ptr<Resetter> preTest(const char* filename) override
+    {
+        if (OString(filename) == "combobox-control.docx" )
+        {
+            std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
+            officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(true, batch);
+            batch->commit();
+        }
+        return nullptr;
+    }
+
+    void verifyComboBoxExport(bool aComboBoxAsDropDown);
 };
 
 DECLARE_OOXMLEXPORT_TEST(testRelorientation, "relorientation.docx")
@@ -765,12 +781,48 @@ DECLARE_OOXMLEXPORT_TEST(testFDO76312, "FDO76312.docx")
     assertXPath(pXmlDoc, "/w:document/w:body/w:tbl[1]/w:tr[1]/w:tc[1]");
 }
 
-DECLARE_OOXMLEXPORT_TEST(testComboBoxControl, "combobox-control.docx")
+void Test::verifyComboBoxExport(bool aComboBoxAsDropDown)
+{
+    if (aComboBoxAsDropDown)
+    {
+        // ComboBox was imported as DropDown text field
+        uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+        uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+        uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+        CPPUNIT_ASSERT(xFields->hasMoreElements());
+        uno::Any aField = xFields->nextElement();
+        uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown"));
+
+        uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items");
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aItems.getLength());
+        CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]);
+        CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]);
+        CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), aItems[2]);
+    }
+    else
+    {
+        uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+        uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+        uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+        uno::Reference<drawing::XControlShape> xControl(xShape, uno::UNO_QUERY);
+
+        CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), getProperty<OUString>(xControl->getControl(), "Text"));
+
+        uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(xControl->getControl(), "StringItemList");
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength());
+        CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]);
+        CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]);
+    }
+}
+
+DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testComboBoxControl, "combobox-control.docx")
 {
     // check XML
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
     if (!pXmlDoc)
         return;
+
     assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dropDownList/w:listItem[1]", "value", "manolo");
     assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:dropDownList/w:listItem[2]", "value", "pepito");
     assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtContent/w:r/w:t", "Manolo");
@@ -779,35 +831,27 @@ DECLARE_OOXMLEXPORT_TEST(testComboBoxControl, "combobox-control.docx")
     uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
 
     // check imported control
-    if (xDrawPage->getCount() > 0)
-    {
-        uno::Reference<drawing::XControlShape> xControl(getShape(1), uno::UNO_QUERY);
+    verifyComboBoxExport(xDrawPage->getCount() == 0);
+}
 
-        CPPUNIT_ASSERT_EQUAL(OUString("Manolo"), getProperty<OUString>(xControl->getControl(), "Text"));
+CPPUNIT_TEST_FIXTURE(Test, tdf134043_ImportComboBoxAsDropDown_true)
+{
+    std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
+    officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(true, batch);
+    batch->commit();
 
-        uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(xControl->getControl(), "StringItemList");
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength());
-        CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]);
-        CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]);
-    }
-    else
-    {
-        // ComboBox was imported as DropDown text field
-        uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
-        uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
-        uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
-        CPPUNIT_ASSERT(xFields->hasMoreElements());
-        uno::Any aField = xFields->nextElement();
-        uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
-        CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown"));
+    load(mpTestDocumentPath, "combobox-control.docx");
+    verifyComboBoxExport(true);
+}
 
-        CPPUNIT_ASSERT_EQUAL(OUString("manolo"), getProperty<OUString>(aField, "SelectedItem"));
+CPPUNIT_TEST_FIXTURE(Test, tdf134043_ImportComboBoxAsDropDown_false)
+{
+    std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
+    officecfg::Office::Writer::Filter::Import::DOCX::ImportComboBoxAsDropDown::set(false, batch);
+    batch->commit();
 
-        uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items");
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength());
-        CPPUNIT_ASSERT_EQUAL(OUString("manolo"), aItems[0]);
-        CPPUNIT_ASSERT_EQUAL(OUString("pepito"), aItems[1]);
-    }
+    load(mpTestDocumentPath, "combobox-control.docx");
+    verifyComboBoxExport(false);
 }
 
 DECLARE_OOXMLEXPORT_TEST(testCheckBoxControl, "checkbox-control.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index 0e1416b7ee00..fbe8d9d01421 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -959,9 +959,10 @@ DECLARE_OOXMLEXPORT_TEST(testN779630, "n779630.docx")
         CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.textfield.DropDown"));
 
         uno::Sequence<OUString> aItems = getProperty< uno::Sequence<OUString> >(aField, "Items");
-        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aItems.getLength());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aItems.getLength());
         CPPUNIT_ASSERT_EQUAL(OUString("Yes"), aItems[0]);
         CPPUNIT_ASSERT_EQUAL(OUString("No"), aItems[1]);
+        CPPUNIT_ASSERT_EQUAL(OUString("dropdown default text"), aItems[2]);
     }
 }
 
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index 3685e92cf942..154e7660d842 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -93,6 +93,15 @@ void SdtHelper::createDropDownControl()
             m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.TextField.DropDown"),
             uno::UNO_QUERY);
 
+        const auto it = std::find_if(
+            m_aDropDownItems.begin(), m_aDropDownItems.end(),
+            [aDefaultText](const OUString& item) -> bool { return !item.compareTo(aDefaultText); });
+
+        if (m_aDropDownItems.end() == it)
+        {
+            m_aDropDownItems.push_back(aDefaultText);
+        }
+
         // set properties
         uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
         xPropertySet->setPropertyValue("SelectedItem", uno::makeAny(aDefaultText));
commit a99de4981f2e0a652d964c8c688f73485494102e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 10 19:14:54 2020 +0200
Commit:     Xisco Fauli <xiscofauli at libreoffice.org>
CommitDate: Tue Aug 11 17:38:00 2020 +0200

    tdf#128198 sw: text formatting: only consider upper margin for first line
    
    The non-first lines start below the first one so the margin is already
    included in the previous line's Y position.
    
    Also move the testTdf116486 to layout.cxx.
    
    (regression from d07fc485d46f431405a3f6a002f951a08c559677)
    
    Change-Id: I574516ea5f9600e2d861e43162b1a69488c68819
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100440
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 99ef50f97b6d8461b8953c2555298c7bbeb3405b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100499
    Reviewed-by: Xisco Fauli <xiscofauli at libreoffice.org>

diff --git a/sw/qa/extras/ooxmlimport/data/tdf116486.docx b/sw/qa/extras/layout/data/tdf116486.docx
similarity index 100%
rename from sw/qa/extras/ooxmlimport/data/tdf116486.docx
rename to sw/qa/extras/layout/data/tdf116486.docx
diff --git a/sw/qa/extras/layout/data/tdf128198-1.docx b/sw/qa/extras/layout/data/tdf128198-1.docx
new file mode 100644
index 000000000000..7c9974d562b9
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf128198-1.docx differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 6ce67106162d..c94811b4d5e7 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -1139,6 +1139,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testRedlineFlysInFootnote)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf116486)
+{
+    SwDoc* pDoc = createDoc("tdf116486.docx");
+    CPPUNIT_ASSERT(pDoc);
+    OUString aTop = parseDump("/root/page/body/txt/Special", "nHeight");
+    CPPUNIT_ASSERT_EQUAL(OUString("4006"), aTop);
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf128198)
+{
+    SwDoc* pDoc = createDoc("tdf128198-1.docx");
+    CPPUNIT_ASSERT(pDoc);
+    xmlDocPtr pLayout = parseLayoutDump();
+    // the problem was that line 5 was truncated at "this  "
+    // due to the fly anchored in previous paragraph
+    assertXPath(pLayout, "/root/page/body/txt[2]/LineBreak[5]", "Line",
+                "to access any service, any time, anywhere. From this  perspective, satellite "
+                "boasts some ");
+    assertXPath(pLayout, "/root/page/body/txt[2]/LineBreak[6]", "Line", "significant advantages. ");
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testNoLineBreakAtSlash)
 {
     load(DATA_DIRECTORY, "no-line-break-at-slash.fodt");
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index a14b97aec66a..4b69a62859c6 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -411,12 +411,6 @@ DECLARE_OOXMLIMPORT_TEST(testTdf114217, "tdf114217.docx")
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), xDrawPage->getCount());
 }
 
-DECLARE_OOXMLIMPORT_TEST(testTdf116486, "tdf116486.docx")
-{
-    OUString aTop = parseDump("/root/page/body/txt/Special", "nHeight");
-    CPPUNIT_ASSERT_EQUAL(OUString("4006"), aTop);
-}
-
 DECLARE_OOXMLIMPORT_TEST(testTdf119200, "tdf119200.docx")
 {
     auto xPara = getParagraph(1);
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 043f522687de..89c7641df414 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -2296,7 +2296,8 @@ void SwTextFormatter::CalcFlyWidth( SwTextFormatInfo &rInf )
     // tdf#116486: consider also the upper margin from getFramePrintArea because intersections
     //             with this additional space should lead to repositioning of paragraphs
     //             For compatibility we grab a related compat flag:
-    if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS))
+    if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS)
+        && IsFirstTextLine())
     {
         const long nUpper = m_pFrame->getFramePrintArea().Top();
         // Increase the rectangle
commit 0d5affd7a25396dbff866adae524a4c01329801f
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Wed Aug 5 21:08:04 2020 +0100
Commit:     Xisco Fauli <xiscofauli at libreoffice.org>
CommitDate: Mon Aug 10 11:56:32 2020 +0200

    tdf#135098 update SwTableCursor m_SelectedBoxes before merge
    
    so it does not contain the soon to-be-deleted SwTableBox so if the rPam is
    queried via a11y it doesn't claim the deleted cell still exists.
    
    tdf#122844 may be the same issue
    
    Change-Id: I1ac3752676162ba5a29c0916039b2b467e2ac41a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100214
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofauli at libreoffice.org>

diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 00e249b9e0fb..15a49729ce51 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -2280,6 +2280,15 @@ TableMergeErr SwDoc::MergeTable( SwPaM& rPam )
             while( &rPam != ( pTmp = pTmp->GetNext() ))
                 for( int i = 0; i < 2; ++i )
                     pTmp->GetBound( static_cast<bool>(i) ) = *rPam.GetPoint();
+
+            if (SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(&rPam))
+            {
+                // tdf#135098 update selection so rPam's m_SelectedBoxes is updated
+                // to not contain the soon to-be-deleted SwTableBox so if the rPam
+                // is queried via a11y it doesn't claim the deleted cell still
+                // exists
+                pTableCursor->NewTableSelection();
+            }
         }
 
         // Merge them
commit 9b5832cd149e199d61a63801fecb7e3baa8c3662
Author:     Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>
AuthorDate: Thu Aug 6 15:32:09 2020 +0200
Commit:     Gerrit Code Review <gerrit at gerrit.libreoffice.org>
CommitDate: Thu Aug 6 15:32:09 2020 +0200

    Update git submodules
    
    * Update translations from branch 'libreoffice-6-4'
      to d03e92fd5d821662dc0ed7d9a0a2b45da09de8a4
      - update translations for 6.4.6 rc2
    
        and force-fix errors using pocheck
    
        Change-Id: Id908ccd8e13508c60a4a0cd1fbede491bb0bf2bb

diff --git a/translations b/translations
index a86baa6cd143..d03e92fd5d82 160000
--- a/translations
+++ b/translations
@@ -1 +1 @@
-Subproject commit a86baa6cd1436f8de43a415d8b38e3ecce44e647
+Subproject commit d03e92fd5d821662dc0ed7d9a0a2b45da09de8a4


More information about the Libreoffice-commits mailing list