include/oox/export/drawingml.hxx | 8 +- include/systools/curlinit.hxx | 3 - include/tools/UnixWrappers.h | 7 ++ oox/source/drawingml/diagram/diagram.cxx | 22 +++++-- oox/source/drawingml/diagram/diagram.hxx | 10 ++- oox/source/drawingml/shape.cxx | 78 +++++++++++++++++++------- oox/source/export/drawingml.cxx | 59 +++++++++++++++++-- sc/source/core/tool/compiler.cxx | 2 sc/source/filter/excel/xestream.cxx | 2 sc/source/filter/excel/xistyle.cxx | 39 ++++++++----- sc/source/filter/inc/xistyle.hxx | 2 sc/source/ui/cctrl/checklistmenu.cxx | 6 +- sw/qa/core/doc/DocumentRedlineManager.cxx | 45 +++++++++++++++ sw/qa/core/doc/data/fmt.docx |binary sw/source/core/doc/DocumentRedlineManager.cxx | 6 ++ sw/source/ui/fldui/flddinf.cxx | 21 ++++--- sw/source/ui/fldui/flddok.cxx | 16 +++-- sw/source/ui/fldui/fldedt.cxx | 2 sw/source/ui/fldui/fldfunc.cxx | 14 +++- sw/source/ui/fldui/fldref.cxx | 22 +++++-- sw/source/ui/fldui/fldvar.cxx | 18 +++--- sw/source/uibase/uno/unotxdoc.cxx | 5 + sw/uiconfig/swriter/ui/editfielddialog.ui | 18 ++++-- ucb/source/ucp/webdav-curl/CurlSession.cxx | 1 vcl/jsdialog/enabled.cxx | 7 ++ 25 files changed, 318 insertions(+), 95 deletions(-)
New commits: commit 69a1769243aed6af8efb6c5fae5faa2205f95f4b Author: Karthik Godha <[email protected]> AuthorDate: Tue Dec 23 14:15:00 2025 +0530 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 tdf#170094: PPTX->PPTX export SmartArt hyperlinks SmartArt hyperlinks are not preserved after roundtrip. This leads to XML having relationship IDs which are invalid. Change-Id: I3fa3d6f79b8eb8d086b1061d26c30568e3b5793f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196152 Reviewed-by: Michael Stahl <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 5fa0a2caa435..027a7817a4a2 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -519,9 +519,11 @@ public: OString WriteWdpPicture( const OUString& rFileId, const css::uno::Sequence< sal_Int8 >& rPictureData ); OOX_DLLPUBLIC void WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rXShape, sal_Int32 nDiagramId, sal_Int32 nShapeId = -1); - void writeDiagramRels(const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& xRelSeq, - const css::uno::Reference<css::io::XOutputStream>& xOutStream, - std::u16string_view sGrabBagProperyName, int nDiagramId); + void writeDiagramImageRels(const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& xRelSeq, + const css::uno::Reference<css::io::XOutputStream>& xOutStream, + std::u16string_view sGrabBagProperyName, int nDiagramId); + void writeDiagramHlinkRels(const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& xRelSeq, + const css::uno::Reference<css::io::XOutputStream>& xOutStream); static void WriteFromTo(const css::uno::Reference<css::drawing::XShape>& rXShape, const css::awt::Size& aPageSize, const sax_fastparser::FSHelperPtr& pDrawing); diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 84cf631ec455..efec200a9d77 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -153,7 +153,9 @@ uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const { sal_Int32 length = maMainDomMap.size(); - if (maDataRelsMap.hasElements()) + if (getDataImageRelsSeq().hasElements()) + ++length; + if (getDataHlinkRelsSeq().hasElements()) ++length; uno::Sequence<beans::PropertyValue> aValue(length); @@ -165,10 +167,16 @@ uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const ++pValue; } - if (maDataRelsMap.hasElements()) + if (getDataImageRelsSeq().hasElements()) + { + pValue->Name = "OOXDiagramDataImageRels"; + pValue->Value <<= getDataImageRelsSeq(); + ++pValue; + } + if (getDataHlinkRelsSeq().hasElements()) { - pValue->Name = "OOXDiagramDataRels"; - pValue->Value <<= maDataRelsMap; + pValue->Name = "OOXDiagramDataHlinkRels"; + pValue->Value <<= getDataHlinkRelsSeq(); ++pValue; } @@ -335,8 +343,10 @@ void loadDiagram( ShapePtr const & pShape, pDiagram, xRefDataModel); - pDiagram->getDataRelsMap() = pShape->resolveRelationshipsOfTypeFromOfficeDoc( rFilter, - xRefDataModel->getFragmentPath(), u"image" ); + pDiagram->getDataImageRelsSeq() = pShape->resolveRelationshipsOfTypeFromOfficeDoc( + rFilter, xRefDataModel->getFragmentPath(), u"image"); + pDiagram->getDataHlinkRelsSeq() = pShape->resolveRelationshipsOfTypeFromOfficeDoc( + rFilter, xRefDataModel->getFragmentPath(), u"hlink"); // Pass the info to pShape for (auto const& extDrawing : pData->getExtDrawings()) diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index 0a1a59336da9..0a348b22cb20 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -143,7 +143,12 @@ public: DiagramColorMap& getColors() { return maColors; } const DiagramColorMap& getColors() const { return maColors; } DiagramDomMap & getDomMap() { return maMainDomMap; } - css::uno::Sequence< css::uno::Sequence< css::uno::Any > > & getDataRelsMap() { return maDataRelsMap; } + + css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& getDataImageRelsSeq() { return maImageRelsSeq; } + css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& getDataHlinkRelsSeq() { return maHlinkRelsSeq; } + const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& getDataImageRelsSeq() const { return maImageRelsSeq; } + const css::uno::Sequence<css::uno::Sequence<css::uno::Any>>& getDataHlinkRelsSeq() const { return maHlinkRelsSeq; } + void addTo( const ShapePtr & pShape, bool bCreate ); css::uno::Sequence<css::beans::PropertyValue> getDomsAsPropertyValues() const; @@ -159,7 +164,8 @@ private: DiagramQStyleMap maStyles; DiagramColorMap maColors; DiagramDomMap maMainDomMap; - css::uno::Sequence< css::uno::Sequence< css::uno::Any > > maDataRelsMap; + css::uno::Sequence<css::uno::Sequence<css::uno::Any>> maImageRelsSeq; + css::uno::Sequence<css::uno::Sequence<css::uno::Any>> maHlinkRelsSeq; }; typedef std::shared_ptr< Diagram > DiagramPtr; diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 679f4a7d85a8..dece867749bc 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -2891,36 +2891,72 @@ uno::Sequence< uno::Sequence< uno::Any > > Shape::resolveRelationshipsOfTypeFro core::RelationsRef xRels = rFilter.importRelations( sFragment ); if ( xRels ) { - core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc( sType ); - if ( xImageRels ) + if (sType == u"image") { - xRelListTemp.realloc( xImageRels->size() ); - auto pxRelListTemp = xRelListTemp.getArray(); - for (auto const& imageRel : *xImageRels) + core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc(sType); + if (xImageRels) { - uno::Sequence< uno::Any > diagramRelTuple (3); - auto pdiagramRelTuple = diagramRelTuple.getArray(); - // [0] => RID, [1] => InputStream [2] => extension - OUString sRelId = imageRel.second.maId; + xRelListTemp.realloc(xImageRels->size()); + auto pxRelListTemp = xRelListTemp.getArray(); + for (auto const& imageRel : *xImageRels) + { + uno::Sequence<uno::Any> diagramRelTuple(3); + auto pdiagramRelTuple = diagramRelTuple.getArray(); + // [0] => RID, [1] => InputStream [2] => extension + OUString sRelId = imageRel.second.maId; + + pdiagramRelTuple[0] <<= sRelId; + OUString sTarget = xImageRels->getFragmentPathFromRelId(sRelId); + + uno::Reference<io::XInputStream> xImageInputStrm( + rFilter.openInputStream(sTarget), uno::UNO_SET_THROW); + StreamDataSequence dataSeq; + if (rFilter.importBinaryData(dataSeq, sTarget)) + { + pdiagramRelTuple[1] <<= dataSeq; + } - pdiagramRelTuple[0] <<= sRelId; - OUString sTarget = xImageRels->getFragmentPathFromRelId( sRelId ); + pdiagramRelTuple[2] <<= sTarget.copy(sTarget.lastIndexOf(".")); - uno::Reference< io::XInputStream > xImageInputStrm( rFilter.openInputStream( sTarget ), uno::UNO_SET_THROW ); - StreamDataSequence dataSeq; - if ( rFilter.importBinaryData( dataSeq, sTarget ) ) - { - pdiagramRelTuple[1] <<= dataSeq; + pxRelListTemp[counter] = std::move(diagramRelTuple); + ++counter; } + } + } + else if (sType == u"hlink") + { + // Hyperlink can be internal or external + core::RelationsRef xSlideRels = xRels->getRelationsFromTypeFromOfficeDoc(u"slide"); + core::RelationsRef xHlinkRels = xRels->getRelationsFromTypeFromOfficeDoc(u"hyperlink"); - pdiagramRelTuple[2] <<= sTarget.copy( sTarget.lastIndexOf(".") ); + sal_Int32 totalSize + = (xSlideRels ? xSlideRels->size() : 0) + (xHlinkRels ? xHlinkRels->size() : 0); + xRelListTemp.realloc(totalSize); + auto pxRelListTemp = xRelListTemp.getArray(); - pxRelListTemp[counter] = std::move(diagramRelTuple); - ++counter; - } - xRelListTemp.realloc(counter); + // Helper to create relation tuple + auto addRelation = [&](const auto& rel, const OUString& relType) + { + uno::Sequence<uno::Any> tuple(3); + auto pTuple = tuple.getArray(); + pTuple[0] <<= rel.second.maId; + pTuple[1] <<= rel.second.maTarget; + pTuple[2] <<= relType; + pxRelListTemp[counter++] = std::move(tuple); + }; + if (xSlideRels) + { + for (auto const& slideRel : *xSlideRels) + addRelation(slideRel, "slide"); + } + if (xHlinkRels) + { + for (auto const& hlinkRel : *xHlinkRels) + addRelation(hlinkRel, "hyperlink"); + } } + xRelListTemp.realloc(counter); } return xRelListTemp; } diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index ad855af5c862..d96551868793 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -6724,7 +6724,8 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX uno::Reference<xml::dom::XDocument> styleDom; uno::Reference<xml::dom::XDocument> colorDom; uno::Reference<xml::dom::XDocument> drawingDom; - uno::Sequence<uno::Sequence<uno::Any>> xDataRelSeq; + uno::Sequence<uno::Sequence<uno::Any>> xDataImageRelSeq; + uno::Sequence<uno::Sequence<uno::Any>> xDataHlinkRelSeq; uno::Sequence<uno::Any> diagramDrawing; // retrieve the doms from the GrabBag @@ -6747,8 +6748,10 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX diagramDrawing[0] >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only. } - else if (propName == "OOXDiagramDataRels") - rProp.Value >>= xDataRelSeq; + else if (propName == "OOXDiagramDataImageRels") + rProp.Value >>= xDataImageRelSeq; + else if (propName == "OOXDiagramDataHlinkRels") + rProp.Value >>= xDataHlinkRelSeq; } // check that we have the 4 mandatory XDocuments @@ -6893,7 +6896,8 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX uno::Sequence<beans::StringPair>()); // write the associated Images and rels for data file - writeDiagramRels(xDataRelSeq, xDataOutputStream, u"OOXDiagramDataRels", nDiagramId); + writeDiagramImageRels(xDataImageRelSeq, xDataOutputStream, u"OOXDiagramDataRels", nDiagramId); + writeDiagramHlinkRels(xDataHlinkRelSeq, xDataOutputStream); // write layout file serializer.set(layoutDom, uno::UNO_QUERY); @@ -6934,12 +6938,12 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX // write the associated Images and rels for drawing file uno::Sequence<uno::Sequence<uno::Any>> xDrawingRelSeq; diagramDrawing[1] >>= xDrawingRelSeq; - writeDiagramRels(xDrawingRelSeq, xDrawingOutputStream, u"OOXDiagramDrawingRels", nDiagramId); + writeDiagramImageRels(xDrawingRelSeq, xDrawingOutputStream, u"OOXDiagramDrawingRels", nDiagramId); } -void DrawingML::writeDiagramRels(const uno::Sequence<uno::Sequence<uno::Any>>& xRelSeq, - const uno::Reference<io::XOutputStream>& xOutStream, - std::u16string_view sGrabBagProperyName, int nDiagramId) +void DrawingML::writeDiagramImageRels(const uno::Sequence<uno::Sequence<uno::Any>>& xRelSeq, + const uno::Reference<io::XOutputStream>& xOutStream, + std::u16string_view sGrabBagProperyName, int nDiagramId) { // add image relationships of OOXData, OOXDiagram OUString sType(oox::getRelationship(Relationship::IMAGE)); @@ -6997,6 +7001,45 @@ void DrawingML::writeDiagramRels(const uno::Sequence<uno::Sequence<uno::Any>>& x } } +void DrawingML::writeDiagramHlinkRels(const uno::Sequence<uno::Sequence<uno::Any>>& xRelSeq, + const uno::Reference<io::XOutputStream>& xOutStream) +{ + uno::Reference<xml::sax::XWriter> xWriter + = xml::sax::Writer::create(comphelper::getProcessComponentContext()); + xWriter->setOutputStream(xOutStream); + + // retrieve the relationships from Sequence + for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++) + { + // diagramDataRelTuple[0] => RID, + // diagramDataRelTuple[1] => Target + // diagramDataRelTuple[2] => Type + const uno::Sequence<uno::Any>& diagramDataRelTuple = xRelSeq[j]; + + OUString sRelId; + OUString sTarget; + OUString sType; + diagramDataRelTuple[0] >>= sRelId; + sRelId = sRelId.copy(3); + diagramDataRelTuple[1] >>= sTarget; + diagramDataRelTuple[2] >>= sType; + + OUString sRelType; + bool bExtURL = true; + if (sType == u"slide") + { + sRelType = oox::getRelationship(Relationship::SLIDE); + bExtURL = false; + } + else + sRelType = oox::getRelationship(Relationship::HYPERLINK); + + PropertySet aProps(xOutStream); + aProps.setAnyProperty(PROP_RelId, uno::Any(sRelId.toInt32())); + mpFB->addRelation(xOutStream, sRelType, sTarget, bExtURL); + } +} + void DrawingML::WriteFromTo(const uno::Reference<css::drawing::XShape>& rXShape, const awt::Size& aPageSize, const FSHelperPtr& pDrawing) { commit 6a1c708b75cd031a129c0703068dbd4d1e427c75 Author: Karthik Godha <[email protected]> AuthorDate: Thu Jan 1 15:49:25 2026 +0530 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 tdf#170189: XLS->XLSX empty font-name in export <font> element in xl/styles.xml can't contaim empty "val" attribute in its name Change-Id: Ib476f23010a54f64cf90619f2712082785e4526a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196387 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Stahl <[email protected]> diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 0540c779f40d..db04d2d6812c 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -899,6 +899,8 @@ sax_fastparser::FSHelperPtr XclXmlUtils::WriteFontData( sax_fastparser::FSHelper pStream->singleElement(XML_color, XML_rgb, XclXmlUtils::ToOString(rComplexColor.getFinalColor())); } + + assert(!rFontData.maName.isEmpty() && "Font Name can't be empty"); pStream->singleElement(nFontId, XML_val, rFontData.maName); pStream->singleElement(XML_family, XML_val, OString::number( rFontData.mnFamily )); if (rFontData.mnCharSet != 0) diff --git a/sc/source/filter/excel/xistyle.cxx b/sc/source/filter/excel/xistyle.cxx index 8a60750716c8..b421ceed9311 100644 --- a/sc/source/filter/excel/xistyle.cxx +++ b/sc/source/filter/excel/xistyle.cxx @@ -567,34 +567,47 @@ const XclImpFont* XclImpFontBuffer::GetFont( sal_uInt16 nFontIndex ) const This also means that entries above 4 are out by one in the list. */ if (nFontIndex == 4) + { return &maFont4; - - if (nFontIndex < 4) + } + else if (nFontIndex < 4) { // Font ID is zero-based when it's less than 4. - return nFontIndex >= maFontList.size() ? nullptr : &maFontList[nFontIndex]; + if (nFontIndex < maFontList.size() && maFontList[nFontIndex].has_value()) + return &maFontList[nFontIndex].value(); } - - // Font ID is greater than 4. It is now 1-based. - return nFontIndex > maFontList.size() ? nullptr : &maFontList[nFontIndex-1]; + else + { + // Font ID is greater than 4. It is now 1-based. + if (--nFontIndex < maFontList.size() && maFontList[nFontIndex].has_value()) + return &maFontList[nFontIndex].value(); + } + return nullptr; } void XclImpFontBuffer::ReadFont( XclImpStream& rStrm ) { - maFontList.emplace_back( GetRoot() ); - XclImpFont& rFont = maFontList.back(); - rFont.ReadFont( rStrm ); + XclImpFont aFont(GetRoot()); + aFont.ReadFont(rStrm); + + // If font-name is empty, remove it from the list + if (aFont.GetFontData().maName.isEmpty()) + { + maFontList.emplace_back(std::nullopt); + return; + } + maFontList.emplace_back(aFont); - if( maFontList.size() == 1 ) + if (maFontList.size() == 1) { - UpdateAppFont( rFont.GetFontData(), rFont.HasCharSet() ); + UpdateAppFont(aFont.GetFontData(), aFont.HasCharSet()); } } void XclImpFontBuffer::ReadEfont( XclImpStream& rStrm ) { - if( !maFontList.empty() ) - maFontList.back().ReadEfont( rStrm ); + if (!maFontList.empty() && maFontList.back().has_value()) + maFontList.back().value().ReadEfont(rStrm); } void XclImpFontBuffer::FillToItemSet( diff --git a/sc/source/filter/inc/xistyle.hxx b/sc/source/filter/inc/xistyle.hxx index ff56c5d1d370..e0839f9d686c 100644 --- a/sc/source/filter/inc/xistyle.hxx +++ b/sc/source/filter/inc/xistyle.hxx @@ -193,7 +193,7 @@ private: void UpdateAppFont( const XclFontData& rFontData, bool bHasCharSet ); private: - std::vector< XclImpFont > maFontList; /// List of all FONT records in the Excel file. + std::vector<std::optional<XclImpFont>> maFontList; /// List of all FONT records in the Excel file. XclFontData maAppFont; /// Application font (for column width). XclImpFont maFont4; /// Built-in font with index 4. XclImpFont maCtrlFont; /// BIFF5 default form controls font (Helv,8pt,bold). commit 8620f1fbaf675b83b2f9784f55a73e90dd7d52b5 Author: Karthik Godha <[email protected]> AuthorDate: Mon Jan 5 18:49:37 2026 +0530 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 tdf#170201: Use #NA! err string for array formulas This is related to 9eed2e4f491cb4f5432157eec77e6f5b525acb8f, instead of using '0' for empty values in array formulas use NotAvailable error string Change-Id: I811745e65d8dd75dbb2e53b918490e7bb66d6cfd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196652 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Stahl <[email protected]> diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 478100909ce6..1d7464de06d4 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -5475,7 +5475,7 @@ void ScCompiler::CreateStringFromMatrix( OUStringBuffer& rBuffer, const FormulaT } } else if( pMatrix->IsEmpty( nC, nR ) ) - AppendDouble(rBuffer, 0); + rBuffer.append(ScGlobal::GetErrorString(FormulaError::NotAvailable)); else if( pMatrix->IsStringOrEmpty( nC, nR ) ) AppendString( rBuffer, pMatrix->GetString(nC, nR).getString() ); } commit fbf036da443f98149342a0c3b051d2712d6554fb Author: Skyler Grey <[email protected]> AuthorDate: Wed Jan 7 11:38:56 2026 +0000 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 feat(jsdialog): hide field reference search It's another core-side filter box. Similarly to the previous change (I40c2565920d1faf42e91d5b523a944776a6a6964) we would like to filter on the client Therefore, we need to hide the search bar here too Change-Id: Ibf524bcecdf7384bc068d4c21cb5608e6a6a6964 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196726 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Szymon Kłos <[email protected]> diff --git a/sw/source/ui/fldui/fldref.cxx b/sw/source/ui/fldui/fldref.cxx index 842255acb6ac..aa1ca95f9d0a 100644 --- a/sw/source/ui/fldui/fldref.cxx +++ b/sw/source/ui/fldui/fldref.cxx @@ -110,6 +110,12 @@ SwFieldRefPage::SwFieldRefPage(weld::Container* pPage, weld::DialogController* p m_xTypeLB->clear(); + if (comphelper::LibreOfficeKit::isActive()) { + // In LOK (read: under JSDialog), it is preferable to run this search on + // the client side rather than in core for positioning/interference/etc. reasons + m_xFilterED->hide(); + } + m_xNameED->connect_changed(LINK(this, SwFieldRefPage, ModifyHdl)); m_xFilterED->connect_changed( LINK( this, SwFieldRefPage, ModifyHdl_Impl ) ); commit ca237b31db3d8c21d4d40c20d53a003551431670 Author: Skyler Grey <[email protected]> AuthorDate: Mon Dec 15 16:57:47 2025 +0000 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 feat(jsdialog): hide checklist menu search The checklist menu has a search bar here, which can be used to filter the items sent by LOK. In Collabora Online, we're changing over to a client-side search bar, which has advantages comprising: - Doing the filtering on the client is pretty easy - We can integrate it better into the listbox - We can expand it to more lists than just checkbox lists very easily If we do that, we shouldn't have the duplicate search bar. Let's remove it... Change-Id: I40c2565920d1faf42e91d5b523a944776a6a6964 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195719 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Szymon Kłos <[email protected]> diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index c1d5f64ca37c..fb0e132ba8e6 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -639,7 +639,11 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData mxFieldsComboLabel->hide(); mxFieldsCombo->hide(); } - mxEdSearch->show(); + if (!comphelper::LibreOfficeKit::isActive()) { + // In LOK (read: under JSDialog), it is preferable to run this search on + // the client side rather than in core for positioning/interference/etc. reasons + mxEdSearch->show(); + } mxButtonBox->show(); mxMenu->connect_row_activated(LINK(this, ScCheckListMenuControl, RowActivatedHdl)); commit f52c2de61079f37c6f9f1eff1c9990d6e93661fc Author: Szymon Kłos <[email protected]> AuthorDate: Wed Dec 31 09:24:01 2025 +0000 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:53:02 2026 +0100 jsdialog: enable cross-reference dialogs - disable name reassignment ued for uitests in LOK - it is not supported and fails on asertion - EditFieldDialog had wrong order of items (buttons on top) Change-Id: I111918b808901cfa7b4020c7c352d969ce76d032 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196356 (cherry picked from commit 3532b81f367cdbe9ed73cca1cee3c2c2381f8dae) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196527 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Jenkins diff --git a/sw/source/ui/fldui/flddinf.cxx b/sw/source/ui/fldui/flddinf.cxx index 45186db15c87..2e7b1d96eaea 100644 --- a/sw/source/ui/fldui/flddinf.cxx +++ b/sw/source/ui/fldui/flddinf.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/lok.hxx> #include <sfx2/frame.hxx> #include <svl/numformat.hxx> #include <svl/zforlist.hxx> @@ -85,10 +86,13 @@ SwFieldDokInfPage::SwFieldDokInfPage(weld::Container* pPage, weld::DialogControl if ( pItem ) pItem->GetValue() >>= m_xCustomPropertySet; - // uitests - m_pTypeView->set_buildable_name(u"type-docinf"_ustr); - m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-docinf"); - m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-docinf"); + if (!comphelper::LibreOfficeKit::isActive()) + { + // uitests + m_pTypeView->set_buildable_name(u"type-docinf"_ustr); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-docinf"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-docinf"); + } } SwFieldDokInfPage::~SwFieldDokInfPage() @@ -109,19 +113,22 @@ void SwFieldDokInfPage::Reset(const SfxItemSet* ) if (aCustomProperties.hasElements()) { m_xTypeList->hide(); - m_xTypeList->set_buildable_name(u"type-list"_ustr); + if (!comphelper::LibreOfficeKit::isActive()) + m_xTypeList->set_buildable_name(u"type-list"_ustr); m_xTypeTree->show(); m_pTypeView = m_xTypeTree.get(); } else { m_xTypeTree->hide(); - m_xTypeTree->set_buildable_name(u"type-tree"_ustr); + if (!comphelper::LibreOfficeKit::isActive()) + m_xTypeTree->set_buildable_name(u"type-tree"_ustr); m_xTypeList->show(); m_pTypeView = m_xTypeList.get(); } - m_pTypeView->set_buildable_name(u"type-docinf"_ustr); + if (!comphelper::LibreOfficeKit::isActive()) + m_pTypeView->set_buildable_name(u"type-docinf"_ustr); // initialise TypeListBox m_pTypeView->freeze(); diff --git a/sw/source/ui/fldui/flddok.cxx b/sw/source/ui/fldui/flddok.cxx index 09f80ef53b81..e39f874d3a77 100644 --- a/sw/source/ui/fldui/flddok.cxx +++ b/sw/source/ui/fldui/flddok.cxx @@ -24,6 +24,7 @@ #include "flddok.hxx" #include <swmodule.hxx> #include <wrtsh.hxx> +#include <comphelper/lok.hxx> #include <svl/numformat.hxx> #include <svl/zformat.hxx> #include <o3tl/string_view.hxx> @@ -73,12 +74,15 @@ SwFieldDokPage::SwFieldDokPage(weld::Container* pPage, weld::DialogController* p //enable 'active' language selection m_xNumFormatLB->SetShowLanguageControl(true); - // uitests - m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-doc"); - m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-doc"); - m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-doc"); - m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-doc"); - m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-doc"); + if (!comphelper::LibreOfficeKit::isActive()) + { + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-doc"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-doc"); + m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-doc"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-doc"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-doc"); + } } SwFieldDokPage::~SwFieldDokPage() diff --git a/sw/source/ui/fldui/fldedt.cxx b/sw/source/ui/fldui/fldedt.cxx index 3c1e08744fa3..fb323f47108f 100644 --- a/sw/source/ui/fldui/fldedt.cxx +++ b/sw/source/ui/fldui/fldedt.cxx @@ -99,7 +99,7 @@ void SwFieldEditDlg::EnsureSelection(SwField *pCurField, SwFieldMgr &rMgr) } SwFieldEditDlg::SwFieldEditDlg(SwView const & rVw) - : SfxSingleTabDialogController(rVw.GetViewFrame().GetFrameWeld(), nullptr, + : SfxSingleTabDialogController(rVw.GetViewFrame().GetFrameWeld(), nullptr, u"content"_ustr, u"modules/swriter/ui/editfielddialog.ui"_ustr, u"EditFieldDialog"_ustr) , m_pSh(rVw.GetWrtShellPtr()) , m_xPrevBT(m_xBuilder->weld_button(u"prev"_ustr)) diff --git a/sw/source/ui/fldui/fldfunc.cxx b/sw/source/ui/fldui/fldfunc.cxx index 5d96e3a45129..2de196941c70 100644 --- a/sw/source/ui/fldui/fldfunc.cxx +++ b/sw/source/ui/fldui/fldfunc.cxx @@ -26,6 +26,7 @@ #include "fldfunc.hxx" #include "flddinf.hxx" #include <flddropdown.hxx> +#include <comphelper/lok.hxx> #include <o3tl/string_view.hxx> #define USER_DATA_VERSION_1 "1" @@ -78,11 +79,14 @@ SwFieldFuncPage::SwFieldFuncPage(weld::Container* pPage, weld::DialogController* m_xCond1ED->ShowBrackets(false); m_xCond2ED->ShowBrackets(false); - // uitests - m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-func"); - m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-func"); - m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-func"); - m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-func"); + if (!comphelper::LibreOfficeKit::isActive()) + { + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-func"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-func"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-func"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-func"); + } } SwFieldFuncPage::~SwFieldFuncPage() diff --git a/sw/source/ui/fldui/fldref.cxx b/sw/source/ui/fldui/fldref.cxx index 2de9c8839e39..842255acb6ac 100644 --- a/sw/source/ui/fldui/fldref.cxx +++ b/sw/source/ui/fldui/fldref.cxx @@ -34,6 +34,7 @@ #include <unotools/charclass.hxx> #include <osl/diagnose.h> +#include <comphelper/lok.hxx> #include <comphelper/string.hxx> #include <editeng/frmdiritem.hxx> #include <o3tl/safeint.hxx> @@ -125,12 +126,15 @@ SwFieldRefPage::SwFieldRefPage(weld::Container* pPage, weld::DialogController* p m_xSelectionToolTipLB->connect_row_activated( LINK(this, SwFieldRefPage, TreeViewInsertHdl) ); m_xFilterED->grab_focus(); - // uitests - m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-ref"); - m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-ref"); - m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-ref"); - m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-ref"); - m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-ref"); + if (!comphelper::LibreOfficeKit::isActive()) + { + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-ref"); + m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-ref"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-ref"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-ref"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-ref"); + } } SwFieldRefPage::~SwFieldRefPage() diff --git a/sw/source/ui/fldui/fldvar.cxx b/sw/source/ui/fldui/fldvar.cxx index 73853795bc3d..8885c08c04f1 100644 --- a/sw/source/ui/fldui/fldvar.cxx +++ b/sw/source/ui/fldui/fldvar.cxx @@ -18,6 +18,7 @@ */ #include <swtypes.hxx> +#include <comphelper/lok.hxx> #include <sfx2/linkmgr.hxx> #include <IDocumentFieldsAccess.hxx> #include <usrfld.hxx> @@ -85,13 +86,16 @@ SwFieldVarPage::SwFieldVarPage(weld::Container* pPage, weld::DialogController* p //enable 'active' language selection m_xNumFormatLB->SetShowLanguageControl(true); - // uitests - m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-var"); - m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-var"); - m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-var"); - m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-var"); - m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-var"); - m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-var"); + if (!comphelper::LibreOfficeKit::isActive()) + { + // uitests + m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-var"); + m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-var"); + m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-var"); + m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-var"); + m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-var"); + m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-var"); + } } SwFieldVarPage::~SwFieldVarPage() diff --git a/sw/uiconfig/swriter/ui/editfielddialog.ui b/sw/uiconfig/swriter/ui/editfielddialog.ui index 4578412d44f3..50782016e223 100644 --- a/sw/uiconfig/swriter/ui/editfielddialog.ui +++ b/sw/uiconfig/swriter/ui/editfielddialog.ui @@ -83,9 +83,22 @@ <property name="position">0</property> </packing> </child> + <child> + <object class="GtkBox" id="content"> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">start</property> + <property name="position">0</property> + </packing> + </child> <child> <!-- n-columns=1 n-rows=1 --> - <object class="GtkGrid" id="grid2"> + <object class="GtkGrid" id="EditFieldGrid"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="column_spacing">6</property> @@ -160,9 +173,6 @@ <property name="position">1</property> </packing> </child> - <child> - <placeholder/> - </child> </object> </child> <action-widgets> diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx index 01b6ddf659ba..0e6b999e0365 100644 --- a/vcl/jsdialog/enabled.cxx +++ b/vcl/jsdialog/enabled.cxx @@ -223,6 +223,13 @@ constexpr auto SwriterDialogList { u"modules/swriter/ui/dropdownfielddialog.ui" }, { u"modules/swriter/ui/editsectiondialog.ui" }, { u"modules/swriter/ui/endnotepage.ui" }, + { u"modules/swriter/ui/editfielddialog.ui" }, + { u"modules/swriter/ui/fielddialog.ui" }, + { u"modules/swriter/ui/flddocumentpage.ui" }, + { u"modules/swriter/ui/fldvarpage.ui" }, + { u"modules/swriter/ui/flddocinfopage.ui" }, + { u"modules/swriter/ui/fldrefpage.ui" }, + { u"modules/swriter/ui/fldfuncpage.ui"}, { u"modules/swriter/ui/footendnotedialog.ui" }, { u"modules/swriter/ui/footnoteareapage.ui" }, { u"modules/swriter/ui/footnotepage.ui" }, commit 8ab0462667765c8824246f66e957ce62291e7409 Author: Tor Lillqvist <[email protected]> AuthorDate: Wed Jan 7 15:18:50 2026 +0200 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:39:56 2026 +0100 Make <tools/UnixWrappers.h> more robust Surround with a multiple inclusion guard, and use the modern C++ [[maybe_unused]] thing only when available. Change-Id: Id1eebd65edb6846d1551b56e208917c2c1f6b34d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196681 Tested-by: Tor Lillqvist <[email protected]> Reviewed-by: Tor Lillqvist <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/include/tools/UnixWrappers.h b/include/tools/UnixWrappers.h index bf4e58a17090..dc1c2becd509 100644 --- a/include/tools/UnixWrappers.h +++ b/include/tools/UnixWrappers.h @@ -32,6 +32,9 @@ * All functions behave like the wrapped ones, set errno on errors. */ +#ifndef INCLUDED_TOOLS_UNIXWRAPPERS_H +#define INCLUDED_TOOLS_UNIXWRAPPERS_H + #include <fcntl.h> #include <stdint.h> #include <stdio.h> @@ -74,7 +77,7 @@ extern "C" { #endif -#ifdef __cplusplus +#if defined __cplusplus && __cplusplus >= 201703L #define UNIXWRAPPERS_H_MAYBE_UNUSED [[maybe_unused]] #else #define UNIXWRAPPERS_H_MAYBE_UNUSED @@ -333,4 +336,6 @@ UNIXWRAPPERS_H_MAYBE_UNUSED static const char* wrap_realpath(const char* path, c #undef UNIXWRAPPERS_H_MAYBE_UNUSED +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ commit 1e0bb8e092e8ae36b0177bc0277310cc5750a0f8 Author: Miklos Vajna <[email protected]> AuthorDate: Fri Jan 9 14:27:53 2026 +0100 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:39:29 2026 +0100 ucb curl: don't verify peer in the isExemptVerifyHost() case Try to insert a https:// image URL into Writer when the URL's host is meant to be not verified, 'curl -k' works with the URL but insertion in Writer still fails. Turns out this is an expired self-signed certificate (in a local test env). Mechanism for not verifying SSL certs in the curl session was added in commit 2a5c998d4cdfd54ba65b93318292dab542beaabd (allow an exemption to be made for a specific host, 2024-08-23), but that results in an image insertion failure. Fix the problem by adapting the ucb/ code to do what <https://github.com/curl/curl/blob/470e26ff6eb55e8d18d6fa44104834e9d1f71274/src/config2setopts.c#L375> does for 'curl -k', also clear the CURLOPT_SSL_VERIFYPEER option. With this, inserting https:// images from my local test server works again in Writer. Change-Id: I0c52f6c0c0dfd6ebf0b4081a8088b623935a96f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196924 Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Tested-by: Caolán McNamara <[email protected]> diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index 21fb2640e1b7..608b813f0975 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -826,6 +826,7 @@ CurlSession::CurlSession(uno::Reference<uno::XComponentContext> xContext, } if (HostFilter::isExemptVerifyHost(m_URI.GetHost())) { + rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_SSL_VERIFYPEER, 0L); rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_SSL_VERIFYHOST, 0L); assert(rc == CURLE_OK); } commit 3682264ccf5bda671f4085db4ec5e95a773d3fc3 Author: Miklos Vajna <[email protected]> AuthorDate: Tue Jan 6 09:30:58 2026 +0100 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:39:21 2026 +0100 sw: fix crash in SwXTextDocument::getDocumentSize() gdb on the crashreport core dump: Program terminated with signal SIGSEGV, Segmentation fault. #0 SwViewShell::GetLayout (this=0x0) at /opt/rh/devtoolset-12/root/usr/include/c++/12/bits/shared_ptr_base.h:1665 and #0 SwViewShell::GetLayout (this=0x0) at /opt/rh/devtoolset-12/root/usr/include/c++/12/bits/shared_ptr_base.h:1665 #1 0x000078c9268a799d in SwViewShell::GetDocSize (this=<optimized out>) at sw/source/core/view/viewsh.cxx:2320 #2 0x000078c926ca55e8 in non-virtual thunk to SwXTextDocument::getDocumentSize() () at sw/inc/unotxdoc.hxx:444 #3 0x000078c933bc4e16 in doc_getDocumentSize (pThis=0x8e8cc20, pWidth=0x7ffdd9b4c5e0, pHeight=0x7ffdd9b4c5e8) at desktop/source/lib/init.cxx:4626 Fix it similar to what SwXTextDocument::setPart() does: don't assume that we still have a view shell by the time getDocumentSize() is called, a document teardown may be in progress where we still have a model, but no views anymore. Change-Id: Id2f5ac4bf08601a9664909f5a78322bf41998a86 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196595 Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index fec3025831e5..c244f003507f 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -3381,6 +3381,11 @@ void SwXTextDocument::paintTile( VirtualDevice &rDevice, Size SwXTextDocument::getDocumentSize() { SwViewShell* pViewShell = m_pDocShell->GetWrtShell(); + if (!pViewShell) + { + return Size(); + } + Size aDocSize = pViewShell->GetDocSize(); return Size(aDocSize.Width() + 2 * DOCUMENTBORDER, commit 47fba53d3448a4f5d5731665a401d54b37057f44 Author: Michael Stahl <[email protected]> AuthorDate: Thu Jan 8 16:42:27 2026 +0100 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:39:11 2026 +0100 ucb: webdav-curl: print SAL_WARN if no CA certificates are found Apparently nothing prints the exception message, so make sure this config issue is visible in logs. Change-Id: Idfb18e2fe42aa7bdcc1c8029833657bb8269b980 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196860 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/include/systools/curlinit.hxx b/include/systools/curlinit.hxx index 7d842a8e4c01..281e8b9a1b1e 100644 --- a/include/systools/curlinit.hxx +++ b/include/systools/curlinit.hxx @@ -35,9 +35,8 @@ static void InitCurl_easy(CURL* const pCURL) char const* const path = GetCABundleFile(); if (path == nullptr) { -#if defined EMSCRIPTEN SAL_WARN("ucb.ucp.webdav.curl", "no OpenSSL CA certificate bundle found"); -#else +#if !defined(EMSCRIPTEN) throw css::uno::RuntimeException(u"no OpenSSL CA certificate bundle found"_ustr); #endif } commit 2aeb193cbf5b1d516f4e59db8ca67cad866a119c Author: Miklos Vajna <[email protected]> AuthorDate: Tue Jan 6 08:32:50 2026 +0100 Commit: Andras Timar <[email protected]> CommitDate: Sat Jan 10 14:38:59 2026 +0100 Related: tdf#168751 sw interdependent redlines, format on del: fix del-on-fmt Open the bugdoc which has a <format>BBBCCCDDD</format> redline. Select CCC, press delete: now CCC is only covered by a delete redline instead of a format-on-delete redline. The trouble is in sw::DocumentRedlineManager::PreAppendDeleteRedline(), where rCtx.pRedl (format redline) initially covers BBBCCCDDD, but then it gets reduced to cover only BBB. We also create a pNew redline to cover only DDD. This gives Writer a way to set rCtx.pNewRedl's range to CCC without an overlap. The downside is that now reject-all doesn't modify the format of CCC anymore, so some unexpected boldness remains in the document. Fix this similar to how sw::DocumentRedlineManager::PreAppendForeignRedline()'s rCtx.eCmpPos == SwComparePosition::Inside case works: except there PushData() is used to push the redline data "over" (before creating pNew), and here we use PushData() to push the redline data "under". This way UI creates a model where format is always on top of delete (and not the other way around), which is useful, since DOCX only has markup for that order and ODT explicitly says this order should be used in files. Change-Id: Ida640ad7bb99ed89faef306dac2b840ae3be53f3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196918 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx b/sw/qa/core/doc/DocumentRedlineManager.cxx index d2a51a18d897..11194129f49e 100644 --- a/sw/qa/core/doc/DocumentRedlineManager.cxx +++ b/sw/qa/core/doc/DocumentRedlineManager.cxx @@ -392,6 +392,51 @@ CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatOwn) CPPUNIT_ASSERT(!rRedlineData.Next()); } } + +CPPUNIT_TEST_FIXTURE(Test, testFormatThenDel) +{ + // Given an "AAA <format>BBB CCC DDD</format> EEE" document: + createSwDoc("fmt.docx"); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/true); + // Skip "AAA BBB ". + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 8, /*bBasicCall=*/false); + // Select "CCC". + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 3, /*bBasicCall=*/false); + + // When deleting CCC: + pWrtShell->DelLeft(); + + // Then make sure the resulting new "delete" redline still tracks formatting: + SwDoc* pDoc = pDocShell->GetDoc(); + IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess(); + SwRedlineTable& rRedlines = rIDRA.GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size()); + { + const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType()); + CPPUNIT_ASSERT(!rRedlineData.Next()); + } + { + const SwRedlineData& rRedlineData = rRedlines[1]->GetRedlineData(0); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 (Format) + // - Actual : 1 (Delete) + // i.e. the middle redline was just "delete", not "format-on-delete", so formatting remained + // in the document after reject-all. + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType()); + CPPUNIT_ASSERT(rRedlineData.Next()); + const SwRedlineData& rRedlineData2 = rRedlines[1]->GetRedlineData(1); + CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData2.GetType()); + CPPUNIT_ASSERT(!rRedlineData2.Next()); + } + { + const SwRedlineData& rRedlineData = rRedlines[2]->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType()); + CPPUNIT_ASSERT(!rRedlineData.Next()); + } +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/doc/data/fmt.docx b/sw/qa/core/doc/data/fmt.docx new file mode 100644 index 000000000000..29fa091007e2 Binary files /dev/null and b/sw/qa/core/doc/data/fmt.docx differ diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 1e11885d6e5a..ef0cf2f83ac9 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -2226,6 +2226,12 @@ void DocumentRedlineManager::PreAppendDeleteRedline(AppendRedlineContext& rCtx) { if( *rCtx.pEnd != *rCtx.pRStt ) { + // At this point, rCtx.pRedl is the old format redline and rCtx.pNewRedl is the + // new delete redline. Make sure that when this pNewRedl gets appended, it still + // has the formatting redline data from rCtx.pRedl / pNew, and format is on top + // of delete. + rCtx.pNewRedl->PushData(*rCtx.pRedl); + SwRangeRedline* pNew = new SwRangeRedline( *rCtx.pRedl ); pNew->SetStart( *rCtx.pEnd ); rCtx.pRedl->SetEnd( *rCtx.pStart, rCtx.pREnd );
