sw/inc/hints.hxx                  |    4 ++-
 sw/source/core/attr/hints.cxx     |    7 ++++--
 sw/source/core/doc/docbm.cxx      |   28 ++++++++++++++++++++++++
 sw/source/core/inc/txtfrm.hxx     |    3 ++
 sw/source/core/text/txtfrm.cxx    |   44 +++++++++++++++++++++++++-------------
 sw/source/core/txtnode/ndtxt.cxx  |    7 +++---
 sw/source/core/txtnode/txtedt.cxx |    2 -
 7 files changed, 74 insertions(+), 21 deletions(-)

New commits:
commit 288ad999090d3f88d87f52ff9b292f473f869601
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed May 18 18:31:14 2022 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu May 19 17:45:50 2022 +0200

    sw_fieldmarkhide: fix wrong handling of SwInsText for fieldmarks
    
    For redlines, typically DocumentContentOperationsManager::InsertString()
    will insert text, and it explicitly removes any redlines on the text
    that has been inserted, hence it is always visible - so effectively the
    sw::MergedPara is updated correctly.
    
    However for fieldmarks the situation is different, if the insertion
    happens inside of the part that is hidden in the layout, then it must
    not be inserted into the sw::MergedPara.
    
    Try to figure out which part(s) of a fieldmark the insertion position is
    in and ignore the inserted text as appropriate in
    SwTextFrame::SwClientNotify().
    
    Change-Id: Ic5066b20e9609f50438ca64ac7d2cbd09baeef23
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134611
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/hints.hxx b/sw/inc/hints.hxx
index afaf1d9022d9..9c37399f68f6 100644
--- a/sw/inc/hints.hxx
+++ b/sw/inc/hints.hxx
@@ -80,8 +80,10 @@ class SwInsText final : public SwMsgPoolItem
 public:
     sal_Int32 nPos;
     sal_Int32 nLen;
+    bool isInsideFieldmarkCommand;
+    bool isInsideFieldmarkResult;
 
-    SwInsText( sal_Int32 nP, sal_Int32 nL );
+    SwInsText(sal_Int32 nP, sal_Int32 nL, bool isInFMCommand, bool 
isInFMResult);
 };
 
 class SwDelChr final : public SwMsgPoolItem
diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx
index 81685b777033..8016037bfdb8 100644
--- a/sw/source/core/attr/hints.cxx
+++ b/sw/source/core/attr/hints.cxx
@@ -31,8 +31,11 @@ SwFormatChg::SwFormatChg( SwFormat* pFormat )
 {
 }
 
-SwInsText::SwInsText( sal_Int32 nP, sal_Int32 nL )
-    : SwMsgPoolItem( RES_INS_TXT ), nPos( nP ), nLen( nL )
+SwInsText::SwInsText(sal_Int32 const nP, sal_Int32 const nL, bool const 
isInFMCommand, bool const isInFMResult)
+    : SwMsgPoolItem( RES_INS_TXT )
+    , nPos( nP ), nLen( nL )
+    , isInsideFieldmarkCommand(isInFMCommand)
+    , isInsideFieldmarkResult(isInFMResult)
 {
 }
 
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 6bc74340689f..1b283437ab6f 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -1975,4 +1975,32 @@ void DelBookmarks(
     }
 }
 
+namespace sw {
+
+SwInsText MakeSwInsText(SwTextNode & rNode, sal_Int32 const nPos, sal_Int32 
const nLen)
+{
+    SwCursor cursor(SwPosition(rNode, nPos), nullptr);
+    bool isInsideFieldmarkCommand(false);
+    bool isInsideFieldmarkResult(false);
+    while (auto const*const pMark = 
rNode.GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(*cursor.GetPoint()))
+    {
+        if (sw::mark::FindFieldSep(*pMark) < *cursor.GetPoint())
+        {
+            isInsideFieldmarkResult = true;
+        }
+        else
+        {
+            isInsideFieldmarkCommand = true;
+        }
+        *cursor.GetPoint() = pMark->GetMarkStart();
+        if (!cursor.Left(1))
+        {
+            break;
+        }
+    }
+    return SwInsText(nPos, nLen, isInsideFieldmarkCommand, 
isInsideFieldmarkResult);
+}
+
+} // namespace sw
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 49af6a5c2476..1b560e0d2bb3 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -30,6 +30,7 @@ namespace com::sun::star::linguistic2 { class 
XHyphenatedWord; }
 
 namespace sw::mark { class IMark; }
 class SwCharRange;
+class SwInsText;
 class SwTextNode;
 class SwTextAttrEnd;
 class SwTextFormatter;
@@ -146,6 +147,8 @@ bool IsMarkHintHidden(SwRootFrame const& rLayout,
 
 void RecreateStartTextFrames(SwTextNode & rNode);
 
+auto MakeSwInsText(SwTextNode & rNode, sal_Int32 nPos, sal_Int32 nLen) -> 
SwInsText;
+
 /**
  * Decides if rTextNode has a numbering which has layout-level values (e.g. 
Arabic, but not
  * none or bullets).
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 76f05e2c8d80..758eb0bd99e1 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -2148,28 +2148,44 @@ void SwTextFrame::SwClientNotify(SwModify const& 
rModify, SfxHint const& rHint)
             sal_Int32 const nNPos = static_cast<const SwInsText*>(pNew)->nPos;
             sal_Int32 const nNLen = static_cast<const SwInsText*>(pNew)->nLen;
             nPos = MapModelToView(&rNode, nNPos);
-            nLen = TextFrameIndex(nNLen);
-            if (m_pMergedPara)
+            // unlike redlines, inserting into fieldmark must be explicitly 
handled
+            bool isHidden(false);
+            switch (getRootFrame()->GetFieldmarkMode())
             {
-                UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, 
nNLen);
+                case sw::FieldmarkMode::ShowCommand:
+                    isHidden = static_cast<const 
SwInsText*>(pNew)->isInsideFieldmarkResult;
+                break;
+                case sw::FieldmarkMode::ShowResult:
+                    isHidden = static_cast<const 
SwInsText*>(pNew)->isInsideFieldmarkCommand;
+                break;
+                case sw::FieldmarkMode::ShowBoth: // just to avoid the warning
+                break;
             }
-            if( IsIdxInside( nPos, nLen ) )
+            if (!isHidden)
             {
-                if( !nLen )
+                nLen = TextFrameIndex(nNLen);
+                if (m_pMergedPara)
                 {
-                    // Refresh NumPortions even when line is empty!
-                    if( nPos )
-                        InvalidateSize();
+                    UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, 
nNPos, nNLen);
+                }
+                if( IsIdxInside( nPos, nLen ) )
+                {
+                    if( !nLen )
+                    {
+                        // Refresh NumPortions even when line is empty!
+                        if( nPos )
+                            InvalidateSize();
+                        else
+                            Prepare();
+                    }
                     else
-                        Prepare();
+                        InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
                 }
-                else
-                    InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
+                lcl_SetScriptInval( *this, nPos );
+                bSetFieldsDirty = true;
+                lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator+<sal_Int32, 
Tag_TextFrameIndex>);
             }
             lcl_SetWrong( *this, rNode, nNPos, nNLen, true );
-            lcl_SetScriptInval( *this, nPos );
-            bSetFieldsDirty = true;
-            lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator+<sal_Int32, 
Tag_TextFrameIndex>);
         }
         break;
         case RES_DEL_CHR:
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 1932ed689276..691c42e3c900 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -2330,7 +2330,7 @@ OUString SwTextNode::InsertText( const OUString & rStr, 
const SwIndex & rIdx,
 
     if ( HasWriterListeners() )
     {   // send this before messing with hints, which will send RES_UPDATE_ATTR
-        SwInsText aHint( aPos, nLen );
+        SwInsText const aHint(sw::MakeSwInsText(*this, aPos, nLen));
         CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aHint));
     }
 
@@ -2538,7 +2538,8 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const 
SwIndex & rDestStart,
 
     // notify frames - before moving hints, because footnotes
     // want to find their anchor text frame in the follow chain
-    SwInsText aInsHint(nDestStart, nLen);
+    // (also ignore fieldmarks, the caller will recreate frames)
+    SwInsText const aInsHint(nDestStart, nLen, false, false);
     pDest->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, &aInsHint));
     const sw::MoveText aMoveHint(pDest, nDestStart, nTextStartIdx, nLen);
     CallSwClientNotify(aMoveHint);
@@ -3781,7 +3782,7 @@ void SwTextNode::ReplaceText( const SwIndex& rStart, 
const sal_Int32 nDelLen,
 
     if (sInserted.getLength())
     {
-        SwInsText aHint( nStartPos, sInserted.getLength() );
+        SwInsText const aHint(sw::MakeSwInsText(*this, nStartPos, 
sInserted.getLength()));
         CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aHint));
     }
 }
diff --git a/sw/source/core/txtnode/txtedt.cxx 
b/sw/source/core/txtnode/txtedt.cxx
index 1188daef9821..e0ed33f30867 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -2020,7 +2020,7 @@ void SwTextNode::ReplaceTextOnly( sal_Int32 nPos, 
sal_Int32 nLen,
     SwDelText aDelHint( nPos, nTLen );
     CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aDelHint));
 
-    SwInsText aHint( nPos, nTLen );
+    SwInsText const aHint(sw::MakeSwInsText(*this, nPos, nTLen));
     CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aHint));
 }
 

Reply via email to