sw/inc/IDocumentMarkAccess.hxx | 2 + sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 2 - sw/source/core/doc/docbm.cxx | 15 +++++++++ sw/source/uibase/wrtsh/delete.cxx | 10 +++++- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 35 ++++++++++++++++++---- 5 files changed, 55 insertions(+), 9 deletions(-)
New commits: commit 6851182cb61a70d3ebd6ee098e8ba5f23582b352 Author: Michael Stahl <[email protected]> AuthorDate: Fri Oct 11 14:06:25 2019 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Wed Oct 23 13:02:14 2019 +0200 sw: SwWrtShell: delete field command when deleting the field Change-Id: I6dbb7a36bdca103d6e9e72a5b5b48ffc135080a1 Reviewed-on: https://gerrit.libreoffice.org/80676 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index 1e2db2436a61..a076a6dada66 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -343,6 +343,8 @@ class IDocumentMarkAccess static SW_DLLPUBLIC OUString GetCrossRefHeadingBookmarkNamePrefix(); static SW_DLLPUBLIC bool IsLegalPaMForCrossRefHeadingBookmark( const SwPaM& rPaM ); + static void DeleteFieldmarkCommand(::sw::mark::IFieldmark const& rMark); + protected: virtual ~IDocumentMarkAccess() {}; }; diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 88a6019251b4..4f94baab5c90 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -530,6 +530,17 @@ bool IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( const SwPaM& rPa rPaM.End()->nContent.GetIndex() == rPaM.End()->nNode.GetNode().GetTextNode()->Len() ) ); } +void IDocumentMarkAccess::DeleteFieldmarkCommand(::sw::mark::IFieldmark const& rMark) +{ + if (GetType(rMark) != MarkType::TEXT_FIELDMARK) + { + return; // TODO FORMDATE has no command? + } + SwPaM pam(sw::mark::FindFieldSep(rMark), rMark.GetMarkStart()); + ++pam.GetPoint()->nContent; // skip CH_TXT_ATR_FIELDSTART + pam.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(pam); +} + namespace sw { namespace mark { MarkManager::MarkManager(SwDoc& rDoc) @@ -1104,6 +1115,10 @@ namespace sw { namespace mark } virtual ~LazyFieldmarkDeleter() override { + // note: because of the call chain from SwUndoDelete, the field + // command *cannot* be deleted here as it would create a separate + // SwUndoDelete that's interleaved with the SwHistory of the outer + // one - only delete the CH_TXT_ATR_FIELD*! m_pFieldmark->ReleaseDoc(m_pDoc); } }; diff --git a/sw/source/uibase/wrtsh/delete.cxx b/sw/source/uibase/wrtsh/delete.cxx index cbb3fad91b69..4a2420ad7b84 100644 --- a/sw/source/uibase/wrtsh/delete.cxx +++ b/sw/source/uibase/wrtsh/delete.cxx @@ -239,10 +239,13 @@ bool SwWrtShell::DelLeft() const SwPosition* pCurPos = GetCursor()->GetPoint(); SwPosition aPrevChar(*pCurPos); --aPrevChar.nContent; - sw::mark::IFieldmark* pFm = getIDocumentMarkAccess()->getFieldmarkFor(aPrevChar); + sw::mark::IFieldmark* pFm = getIDocumentMarkAccess()->getFieldmarkAt(aPrevChar); if (pFm && pFm->GetMarkEnd() == *pCurPos) { + mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr); + IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm); getIDocumentMarkAccess()->deleteMark(pFm); + mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); return true; } @@ -375,10 +378,13 @@ bool SwWrtShell::DelRight() { // If we are just ahead of a fieldmark, then remove it completely - sw::mark::IFieldmark* pFm = GetCurrentFieldmark(); + sw::mark::IFieldmark *const pFm = getIDocumentMarkAccess()->getFieldmarkAt(*GetCursor()->GetPoint()); if (pFm && pFm->GetMarkStart() == *GetCursor()->GetPoint()) { + mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr); + IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm); getIDocumentMarkAccess()->deleteMark(pFm); + mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); bRet = true; break; } commit f610f9b611fe9f206b872ed06f7e859d688385fc Author: Michael Stahl <[email protected]> AuthorDate: Wed Oct 2 17:15:32 2019 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Wed Oct 23 13:01:53 2019 +0200 writerfilter: import nested generic fields from RTF * for m_bStartGenericField, push new insert position onto the stack in DomainMapper_Impl::CloseFieldCommand(), not in DomainMapper_Impl::appendTextPortion() * how is the field result inserted into the field, instead of after it? - it doesn't seem possible to move the insertion of the field mark to PopFieldContext(), as there's no way to pass 3 positions to attach(), and exposing a writable property for the position(s) is a bad idea - finishParagraph() calls AppendTextNode(), which happily ignores a content index on the given XTextRange - so temporarily insert a paragraph break, override the insert position, and join the paragraphs in PopFieldContext() Change-Id: Ie49084f6ea6451e7d7f9b613cedce326de9a54f1 Reviewed-on: https://gerrit.libreoffice.org/80075 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index e269a3bfba6e..3996c634ab8f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -537,7 +537,7 @@ DECLARE_OOXMLEXPORT_TEST(testSdtDateDuplicate, "sdt-date-duplicate.docx") DECLARE_OOXMLEXPORT_TEST(testFdo81492, "fdo81492.docx") { if (xmlDocPtr pXmlDoc = parseExport()) - assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[1]/w:r[9]/w:instrText", "ADDIN EN.CITE.DATA"); + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p[1]/w:r[7]/w:instrText", "ADDIN EN.CITE.DATA"); } DECLARE_OOXMLEXPORT_TEST(testEditTime, "fdo81341.docx") diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index b9c053700574..b2cb490f221a 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1779,7 +1779,10 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, const Proper m_bTextInserted = true; xTOCTextCursor->gotoRange(xTextRange->getEnd(), true); mxTOCTextCursor = xTOCTextCursor; - m_aTextAppendStack.push(TextAppendContext(xTextAppend, xTOCTextCursor)); + if (!m_bStartGenericField) + { + m_aTextAppendStack.push(TextAppendContext(xTextAppend, xTOCTextCursor)); + } } } else @@ -5029,12 +5032,27 @@ void DomainMapper_Impl::CloseFieldCommand() const uno::Reference<text::XTextContent> xTextContent(xFieldInterface, uno::UNO_QUERY_THROW); uno::Reference< text::XTextAppend > xTextAppend = m_aTextAppendStack.top().xTextAppend; uno::Reference< text::XTextCursor > xCrsr = xTextAppend->createTextCursorByRange(pContext->GetStartRange()); - if (xTextContent.is()) + if (m_aTextAppendStack.top().xInsertPosition.is()) + { + xCrsr->gotoRange(m_aTextAppendStack.top().xInsertPosition, true); + } + else { - xTextAppend->insertTextContent(xCrsr,xTextContent, true); + xCrsr->gotoEnd(true); } - uno::Reference<uno::XInterface> xContent(xTextContent); - uno::Reference< text::XFormField> xFormField(xContent, uno::UNO_QUERY); + xTextAppend->insertTextContent(xCrsr, xTextContent, true); + // problem: the fieldmark must be inserted here, because + // attach() takes 2 positions, not 3! + // FAIL: AppendTextNode() ignores the content index! + // plan B: insert a spurious paragraph break now and join + // it in PopFieldContext()! + xCrsr->gotoRange(xTextContent->getAnchor()->getEnd(), false); + xCrsr->goLeft(1, false); // skip CH_TXT_ATR_FIELDEND + xTextAppend->insertControlCharacter(xCrsr, text::ControlCharacter::PARAGRAPH_BREAK, false); + xCrsr->goLeft(1, false); // back to previous paragraph + m_aTextAppendStack.push(TextAppendContext(xTextAppend, xCrsr)); + + uno::Reference<text::XFormField> xFormField(xTextContent, uno::UNO_QUERY); xFormField->setFieldType(aCode); m_bStartGenericField = true; pContext->SetFormField( xFormField ); @@ -5396,9 +5414,14 @@ void DomainMapper_Impl::PopFieldContext() else if(m_bStartGenericField) { m_bStartGenericField = false; + xCrsr->gotoRange(m_aTextAppendStack.top().xInsertPosition, false); + xCrsr->goRight(1, true); + xCrsr->setString(OUString()); // undo SplitNode from CloseFieldCommand() + // note: paragraph properties will be overwritten + // by finishParagraph() anyway so ignore here + m_aTextAppendStack.pop(); if(m_bTextInserted) { - m_aTextAppendStack.pop(); m_bTextInserted = false; } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
