summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-05-18 18:31:14 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2022-05-19 17:45:50 +0200
commit288ad999090d3f88d87f52ff9b292f473f869601 (patch)
tree335ec80d3373ed7817025574055e640d84527ae2
parent2a813483cdbfb458ce62e8d9bdcf2506c0ed02a9 (diff)
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.stahl@allotropia.de>
-rw-r--r--sw/inc/hints.hxx4
-rw-r--r--sw/source/core/attr/hints.cxx7
-rw-r--r--sw/source/core/doc/docbm.cxx28
-rw-r--r--sw/source/core/inc/txtfrm.hxx3
-rw-r--r--sw/source/core/text/txtfrm.cxx44
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx7
-rw-r--r--sw/source/core/txtnode/txtedt.cxx2
7 files changed, 74 insertions, 21 deletions
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));
}