[Libreoffice-commits] core.git: 2 commits - sw/inc sw/qa sw/source writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Wed Oct 23 11:03:24 UTC 2019


 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 <Michael.Stahl at cib.de>
AuthorDate: Fri Oct 11 14:06:25 2019 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
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 <michael.stahl at cib.de>

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 <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 2 17:15:32 2019 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
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 <michael.stahl at cib.de>

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;
                             }
                         }


More information about the Libreoffice-commits mailing list