desktop/Executable_soffice_bin.mk | 3 solenv/gbuild/platform/unxgcc.mk | 2 static/emscripten/soffice_args.js | 6 sw/source/filter/xml/xmlimp.cxx | 356 +++++++++++++++++++------------------- sw/source/filter/xml/xmlimp.hxx | 1 5 files changed, 185 insertions(+), 183 deletions(-)
New commits: commit 19a73f096a76dd3b650e1f0849dbd42424c50d5b Author: Caolán McNamara <[email protected]> AuthorDate: Fri Jul 26 09:05:56 2024 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Fri Jul 26 11:22:46 2024 +0200 ofz#70674 Null-dereference READ xCursorTunnel.get() is a SvxUnoTextCursor in this case Change-Id: Iaa50a4895923bc1635dc69325203de7bfb77886b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171064 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx index 21cb27ceabc5..6b6831c8bc5a 100644 --- a/sw/source/filter/xml/xmlimp.cxx +++ b/sw/source/filter/xml/xmlimp.cxx @@ -631,179 +631,7 @@ void SwXMLImport::endDocument() if( HasShapeImport() ) ClearShapeImport(); - SwDoc *pDoc = nullptr; - if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() ) - { - Reference<XInterface> xCursorTunnel( GetTextImport()->GetCursor(), - UNO_QUERY); - assert(xCursorTunnel.is() && "missing XUnoTunnel for Cursor"); - OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(xCursorTunnel.get()); - assert(pTextCursor && "SwXTextCursor missing"); - SwPaM *pPaM = pTextCursor->GetPaM(); - if( IsInsertMode() && m_oSttNdIdx->GetIndex() ) - { - // If we are in insert mode, join the split node that is in front - // of the new content with the first new node. Or in other words: - // Revert the first split node. - SwTextNode* pTextNode = m_oSttNdIdx->GetNode().GetTextNode(); - SwNodeIndex aNxtIdx( *m_oSttNdIdx ); - if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx ) && - m_oSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() ) - { - // If the PaM points to the first new node, move the PaM to the - // end of the previous node. - if( pPaM->GetPoint()->GetNode() == aNxtIdx.GetNode() ) - { - pPaM->GetPoint()->Assign( *pTextNode, - pTextNode->GetText().getLength()); - } - -#if OSL_DEBUG_LEVEL > 0 - // !!! This should be impossible !!!! - OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 != - pPaM->GetBound().GetNodeIndex(), - "PaM.Bound1 point to new node " ); - OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 != - pPaM->GetBound( false ).GetNodeIndex(), - "PaM.Bound2 points to new node" ); - - if( m_oSttNdIdx->GetIndex()+1 == - pPaM->GetBound().GetNodeIndex() ) - { - const sal_Int32 nCntPos = - pPaM->GetBound().GetContentIndex(); - pPaM->GetBound().SetContent( - pTextNode->GetText().getLength() + nCntPos ); - } - if( m_oSttNdIdx->GetIndex()+1 == - pPaM->GetBound( false ).GetNodeIndex() ) - { - const sal_Int32 nCntPos = - pPaM->GetBound( false ).GetContentIndex(); - pPaM->GetBound( false ).SetContent( - pTextNode->GetText().getLength() + nCntPos ); - } -#endif - // If the first new node isn't empty, convert the node's text - // attributes into hints. Otherwise, set the new node's - // paragraph style at the previous (empty) node. - SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode(); - if (!pTextNode->GetText().isEmpty()) - pDelNd->FormatToTextAttr( pTextNode ); - else - { - pTextNode->ResetAttr(RES_CHRATR_BEGIN, RES_CHRATR_END); - pTextNode->ChgFormatColl( pDelNd->GetTextColl() ); - if (!pDelNd->GetNoCondAttr(RES_PARATR_LIST_ID, /*bInParents=*/false)) - { - // MergeListsAtDocumentInsertPosition() will deal with lists below, copy - // paragraph direct formatting otherwise. - pDelNd->CopyCollFormat(*pTextNode); - } - } - pTextNode->JoinNext(); - } - } - - SwPosition* pPos = pPaM->GetPoint(); - OSL_ENSURE( !pPos->GetContentIndex(), "last paragraph isn't empty" ); - if( !pPos->GetContentIndex() ) - { - SwTextNode* pCurrNd; - SwNodeOffset nNodeIdx = pPos->GetNodeIndex(); - pDoc = &pPaM->GetDoc(); - - OSL_ENSURE( pPos->GetNode().IsContentNode(), - "insert position is not a content node" ); - if( !IsInsertMode() ) - { - // If we're not in insert mode, the last node is deleted. - const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1]; - if( pPrev->IsContentNode() || - ( pPrev->IsEndNode() && - pPrev->StartOfSectionNode()->IsSectionNode() ) ) - { - SwContentNode* pCNd = pPaM->GetPointContentNode(); - if( pCNd && pCNd->StartOfSectionIndex()+2 < - pCNd->EndOfSectionIndex() ) - { - SwNode& rDelNode = pPaM->GetPoint()->GetNode(); - // move so we don't have a dangling SwContentIndex to the deleted node - pPaM->GetPoint()->Adjust(SwNodeOffset(+1)); - if (pPaM->HasMark()) - pPaM->GetMark()->Adjust(SwNodeOffset(+1)); - pDoc->GetNodes().Delete( rDelNode ); - } - } - } - else if( nullptr != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTextNode()) ) - { - // Id we're in insert mode, the empty node is joined with - // the next and the previous one. - if( pCurrNd->CanJoinNext( pPos )) - { - SwTextNode* pNextNd = pPos->GetNode().GetTextNode(); - bool endNodeFound = pDoc->GetNodes()[nNodeIdx-1]->IsEndNode(); - SwNode *pLastPar = pDoc->GetNodes()[nNodeIdx -2]; - if ( !pLastPar->IsTextNode() ) { - pLastPar = pDoc->GetNodes()[nNodeIdx -1]; - } - if ( !endNodeFound && pLastPar->IsTextNode() ) - { - pNextNd->ChgFormatColl(pLastPar->GetTextNode()->GetTextColl()); - } - - pPaM->SetMark(); pPaM->DeleteMark(); - pNextNd->JoinPrev(); - - // Remove line break that has been inserted by the import, - // but only if one has been inserted and - // no endNode found to avoid removing section - if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && !endNodeFound && - *m_oSttNdIdx != pPos->GetNode() ) - { - pNextNd->JoinPrev(); - } - } - else if (pCurrNd->GetText().isEmpty()) - { - pPaM->SetMark(); pPaM->DeleteMark(); - SwNode& rDelNode = pPos->GetNode(); - // move so we don't have a dangling SwContentIndex to the deleted node - pPaM->GetPoint()->Adjust(SwNodeOffset(+1)); - pDoc->GetNodes().Delete( rDelNode ); - pPaM->Move( fnMoveBackward ); - } - } - - // tdf#113877 - // when we insert one document with list inside into another one with list at the insert position, - // the resulting numbering in these lists is not consequent. - // - // Main document: - // 1. One - // 2. Two - // 3. Three - // 4. <-- insert position - // - // Inserted document: - // 1. One - // 2. Two - // 3. Three - // 4. - // - // Expected result - // 1. One - // 2. Two - // 3. Three - // 4. One - // 5. Two - // 6. Three - // 7. - // - MergeListsAtDocumentInsertPosition(pDoc); - } - } + SwDoc *pDoc = endDocAdjustNodes(); /* Was called too early. Moved from SwXMLBodyContext_Impl::EndElement */ @@ -1069,6 +897,188 @@ void SwXMLImport::MergeListsAtDocumentInsertPosition(SwDoc *pDoc) } } +SwDoc* SwXMLImport::endDocAdjustNodes() +{ + SwDoc *pDoc = nullptr; + if( (getImportFlags() & SvXMLImportFlags::CONTENT) && !IsStylesOnlyMode() ) + { + Reference<XInterface> xCursorTunnel( GetTextImport()->GetCursor(), + UNO_QUERY); + assert(xCursorTunnel.is() && "missing XUnoTunnel for Cursor"); + OTextCursorHelper* pTextCursor = dynamic_cast<OTextCursorHelper*>(xCursorTunnel.get()); + if (!pTextCursor) + { + SAL_WARN("sw", "SwXMLImport::endDocAdjustNodes: SwXTextCursor missing"); + return nullptr; + } + SwPaM *pPaM = pTextCursor->GetPaM(); + if( IsInsertMode() && m_oSttNdIdx->GetIndex() ) + { + // If we are in insert mode, join the split node that is in front + // of the new content with the first new node. Or in other words: + // Revert the first split node. + SwTextNode* pTextNode = m_oSttNdIdx->GetNode().GetTextNode(); + SwNodeIndex aNxtIdx( *m_oSttNdIdx ); + if( pTextNode && pTextNode->CanJoinNext( &aNxtIdx ) && + m_oSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() ) + { + // If the PaM points to the first new node, move the PaM to the + // end of the previous node. + if( pPaM->GetPoint()->GetNode() == aNxtIdx.GetNode() ) + { + pPaM->GetPoint()->Assign( *pTextNode, + pTextNode->GetText().getLength()); + } + +#if OSL_DEBUG_LEVEL > 0 + // !!! This should be impossible !!!! + OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 != + pPaM->GetBound().GetNodeIndex(), + "PaM.Bound1 point to new node " ); + OSL_ENSURE( m_oSttNdIdx->GetIndex()+1 != + pPaM->GetBound( false ).GetNodeIndex(), + "PaM.Bound2 points to new node" ); + + if( m_oSttNdIdx->GetIndex()+1 == + pPaM->GetBound().GetNodeIndex() ) + { + const sal_Int32 nCntPos = + pPaM->GetBound().GetContentIndex(); + pPaM->GetBound().SetContent( + pTextNode->GetText().getLength() + nCntPos ); + } + if( m_oSttNdIdx->GetIndex()+1 == + pPaM->GetBound( false ).GetNodeIndex() ) + { + const sal_Int32 nCntPos = + pPaM->GetBound( false ).GetContentIndex(); + pPaM->GetBound( false ).SetContent( + pTextNode->GetText().getLength() + nCntPos ); + } +#endif + // If the first new node isn't empty, convert the node's text + // attributes into hints. Otherwise, set the new node's + // paragraph style at the previous (empty) node. + SwTextNode* pDelNd = aNxtIdx.GetNode().GetTextNode(); + if (!pTextNode->GetText().isEmpty()) + pDelNd->FormatToTextAttr( pTextNode ); + else + { + pTextNode->ResetAttr(RES_CHRATR_BEGIN, RES_CHRATR_END); + pTextNode->ChgFormatColl( pDelNd->GetTextColl() ); + if (!pDelNd->GetNoCondAttr(RES_PARATR_LIST_ID, /*bInParents=*/false)) + { + // MergeListsAtDocumentInsertPosition() will deal with lists below, copy + // paragraph direct formatting otherwise. + pDelNd->CopyCollFormat(*pTextNode); + } + } + pTextNode->JoinNext(); + } + } + + SwPosition* pPos = pPaM->GetPoint(); + OSL_ENSURE( !pPos->GetContentIndex(), "last paragraph isn't empty" ); + if( !pPos->GetContentIndex() ) + { + SwTextNode* pCurrNd; + SwNodeOffset nNodeIdx = pPos->GetNodeIndex(); + pDoc = &pPaM->GetDoc(); + + OSL_ENSURE( pPos->GetNode().IsContentNode(), + "insert position is not a content node" ); + if( !IsInsertMode() ) + { + // If we're not in insert mode, the last node is deleted. + const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1]; + if( pPrev->IsContentNode() || + ( pPrev->IsEndNode() && + pPrev->StartOfSectionNode()->IsSectionNode() ) ) + { + SwContentNode* pCNd = pPaM->GetPointContentNode(); + if( pCNd && pCNd->StartOfSectionIndex()+2 < + pCNd->EndOfSectionIndex() ) + { + SwNode& rDelNode = pPaM->GetPoint()->GetNode(); + // move so we don't have a dangling SwContentIndex to the deleted node + pPaM->GetPoint()->Adjust(SwNodeOffset(+1)); + if (pPaM->HasMark()) + pPaM->GetMark()->Adjust(SwNodeOffset(+1)); + pDoc->GetNodes().Delete( rDelNode ); + } + } + } + else if( nullptr != (pCurrNd = pDoc->GetNodes()[nNodeIdx]->GetTextNode()) ) + { + // Id we're in insert mode, the empty node is joined with + // the next and the previous one. + if( pCurrNd->CanJoinNext( pPos )) + { + SwTextNode* pNextNd = pPos->GetNode().GetTextNode(); + bool endNodeFound = pDoc->GetNodes()[nNodeIdx-1]->IsEndNode(); + SwNode *pLastPar = pDoc->GetNodes()[nNodeIdx -2]; + if ( !pLastPar->IsTextNode() ) { + pLastPar = pDoc->GetNodes()[nNodeIdx -1]; + } + if ( !endNodeFound && pLastPar->IsTextNode() ) + { + pNextNd->ChgFormatColl(pLastPar->GetTextNode()->GetTextColl()); + } + + pPaM->SetMark(); pPaM->DeleteMark(); + pNextNd->JoinPrev(); + + // Remove line break that has been inserted by the import, + // but only if one has been inserted and + // no endNode found to avoid removing section + if( pNextNd->CanJoinPrev(/* &pPos->nNode*/ ) && !endNodeFound && + *m_oSttNdIdx != pPos->GetNode() ) + { + pNextNd->JoinPrev(); + } + } + else if (pCurrNd->GetText().isEmpty()) + { + pPaM->SetMark(); pPaM->DeleteMark(); + SwNode& rDelNode = pPos->GetNode(); + // move so we don't have a dangling SwContentIndex to the deleted node + pPaM->GetPoint()->Adjust(SwNodeOffset(+1)); + pDoc->GetNodes().Delete( rDelNode ); + pPaM->Move( fnMoveBackward ); + } + } + + // tdf#113877 + // when we insert one document with list inside into another one with list at the insert position, + // the resulting numbering in these lists is not consequent. + // + // Main document: + // 1. One + // 2. Two + // 3. Three + // 4. <-- insert position + // + // Inserted document: + // 1. One + // 2. Two + // 3. Three + // 4. + // + // Expected result + // 1. One + // 2. Two + // 3. Three + // 4. One + // 5. Two + // 6. Three + // 7. + // + MergeListsAtDocumentInsertPosition(pDoc); + } + } + return pDoc; +} + namespace { // Locally derive XMLTextShapeImportHelper, so we can take care of the diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx index 4c528155f24c..4e800da42017 100644 --- a/sw/source/filter/xml/xmlimp.hxx +++ b/sw/source/filter/xml/xmlimp.hxx @@ -96,6 +96,7 @@ class SwXMLImport: public SvXMLImport const css::uno::Reference< css::text::XTextRange > & rInsertPos ); void setStyleInsertMode( SfxStyleFamily nFamilies, bool bOverwrite ); + SwDoc* endDocAdjustNodes(); protected: commit 6148e1a0e01eac6159a6ce618f30975569dc5c94 Author: Stephan Bergmann <[email protected]> AuthorDate: Fri Jul 26 09:18:03 2024 +0200 Commit: Stephan Bergmann <[email protected]> CommitDate: Fri Jul 26 11:22:37 2024 +0200 Looks like Emscripten LO doesn't need explicit --norestore --nologo ...mostly because the relevant parts of the code are hard-disabled (even if you would --disable-wasm-strip) with ENABLE_WASM_STRIP_RECOVERYUI=TRUE and ENABLE_WASM_STRIP_SPLASH=TRUE. (And if there are places in the code that would need the equivalent of either --norestore or --nologo after all, we could probably better add explicit #if EMSCRIPTEN there instead.) This allows to get rid of hard-coding the Qt Emscripten LO command line arguments, which means that e.g. web applications embedding LO would now be able to specify them themselves. Change-Id: I8e2dcfd170cc32276bfb9007f098f6ae6a7f9ec1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171063 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <[email protected]> diff --git a/desktop/Executable_soffice_bin.mk b/desktop/Executable_soffice_bin.mk index f159c877f447..df1db8ae1260 100644 --- a/desktop/Executable_soffice_bin.mk +++ b/desktop/Executable_soffice_bin.mk @@ -33,9 +33,6 @@ $(call gb_LinkTarget_get_target,$(call gb_Executable_get_linktarget,soffice_bin) # don't sort; later can override previous settings! $(eval $(call gb_Executable_add_prejs,soffice_bin,$(SRCDIR)/static/emscripten/environment.js)) $(eval $(call gb_Executable_add_prejs,soffice_bin,$(gb_CustomTarget_workdir)/static/emscripten_fs_image/soffice.data.js.link)) -ifeq ($(ENABLE_QT5),TRUE) -$(eval $(call gb_Executable_add_prejs,soffice_bin,$(SRCDIR)/static/emscripten/soffice_args.js)) -endif endif ifeq ($(OS),WNT) diff --git a/solenv/gbuild/platform/unxgcc.mk b/solenv/gbuild/platform/unxgcc.mk index 591eceeb9839..0e4f01b4249e 100644 --- a/solenv/gbuild/platform/unxgcc.mk +++ b/solenv/gbuild/platform/unxgcc.mk @@ -185,7 +185,7 @@ $(if $(filter TRUE,$(ENABLE_QT5)), \ sed -e 's/@APPNAME@/$(subst $(gb_Executable_EXT),,$(notdir $(1)))/' $(QT5_PLATFORMS_SRCDIR)/wasm_shell.html > $(dir $(1))qt_$(notdir $(1)) && \ cp $(QT5_PLATFORMS_SRCDIR)/qtlogo.svg $(QT5_PLATFORMS_SRCDIR)/qtloader.js $(dir $(1)) && \ ,$(if $(filter TRUE,$(ENABLE_QT6)), \ - sed -e 's/@APPNAME@/$(basename $(notdir $(1)))/g' -e 's/@APPEXPORTNAME@/$(basename $(notdir $(1)))_entry/g' -e 's/@PRELOAD@//g' -e 's|const instance = await qtLoad$(OPEN_PAREN){|const instance = await qtLoad$(OPEN_PAREN){ "arguments": ["--norestore"$(COMMA) "--nologo"]$(COMMA)|' -e 's/}$(CLOSE_PAREN);$$/}$(CLOSE_PAREN); window.Module = instance;/' $(QT6_PLATFORMS_SRCDIR)/wasm_shell.html > $(dir $(1))qt_$(basename $(notdir $(1))).html && \ + sed -e 's/@APPNAME@/$(basename $(notdir $(1)))/g' -e 's/@APPEXPORTNAME@/$(basename $(notdir $(1)))_entry/g' -e 's/@PRELOAD@//g' -e 's/}$(CLOSE_PAREN);$$/}$(CLOSE_PAREN); window.Module = instance;/' $(QT6_PLATFORMS_SRCDIR)/wasm_shell.html > $(dir $(1))qt_$(basename $(notdir $(1))).html && \ cp $(QT6_PLATFORMS_SRCDIR)/qtlogo.svg $(QT6_PLATFORMS_SRCDIR)/qtloader.js $(dir $(1)) && \ )) \ cp $(gb_CustomTarget_workdir)/static/emscripten_fs_image/soffice.data $(dir $(1))/soffice.data && \ diff --git a/static/emscripten/soffice_args.js b/static/emscripten/soffice_args.js deleted file mode 100644 index 7656c7edee7e..000000000000 --- a/static/emscripten/soffice_args.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; - -Module['arguments'] = [ - '--norestore', - '--nologo' -];
