sw/source/core/layout/wsfrm.cxx  |   10 +-
 sw/source/core/text/redlnitr.cxx |  181 +++++++++++++++++++++++++++++++++------
 2 files changed, 162 insertions(+), 29 deletions(-)

New commits:
commit aacaa2aa91f705d64b929b5cff2872f160021b9f
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Nov 3 22:11:59 2020 +0100
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Tue Nov 17 22:19:32 2020 +0100

    sw_fieldmarkhide: let CheckParaRedlineMerge() hide fieldmarks
    
    HideIterator finds the next delete redline or fieldmark, whichever is
    closer.
    
    Change-Id: I4c6eac864da4b4bf531437e555a3994fd2670367
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105984
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>

diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 6727751c3576..a79ce4878a89 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -35,6 +35,9 @@
 #include <doc.hxx>
 #include <IDocumentRedlineAccess.hxx>
 #include <IDocumentLayoutAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
 #include <rootfrm.hxx>
 #include <breakit.hxx>
 #include <vcl/commandevent.hxx>
@@ -47,14 +50,161 @@
 
 using namespace ::com::sun::star;
 
+namespace {
+
+class HideIterator
+{
+private:
+    IDocumentRedlineAccess const& m_rIDRA;
+    IDocumentMarkAccess const& m_rIDMA;
+    bool const m_isHideRedlines;
+    sw::FieldmarkMode const m_eFieldmarkMode;
+    SwPosition const m_Start;
+    /// next redline
+    SwRedlineTable::size_type m_RedlineIndex;
+    /// next fieldmark
+    std::pair<sw::mark::IFieldmark const*, std::unique_ptr<SwPosition>> 
m_Fieldmark;
+    std::optional<SwPosition> m_oNextFieldmarkHide;
+    /// current start/end pair
+    SwPosition const* m_pStartPos;
+    SwPosition const* m_pEndPos;
+
+public:
+    SwPosition const* GetStartPos() const { return m_pStartPos; }
+    SwPosition const* GetEndPos() const { return m_pEndPos; }
+
+    HideIterator(SwTextNode & rTextNode,
+            bool const isHideRedlines, sw::FieldmarkMode const eMode)
+        : m_rIDRA(rTextNode.getIDocumentRedlineAccess())
+        , m_rIDMA(*rTextNode.getIDocumentMarkAccess())
+        , m_isHideRedlines(isHideRedlines)
+        , m_eFieldmarkMode(eMode)
+        , m_Start(rTextNode, 0)
+        , m_RedlineIndex(m_rIDRA.GetRedlinePos(rTextNode, RedlineType::Any))
+        , m_pStartPos(nullptr)
+        , m_pEndPos(&m_Start)
+    {
+    }
+
+    // delete redlines and fieldmarks can't overlap, due to sw::CalcBreaks()
+    // and no combining of adjacent redlines
+    // -> dummy chars are delete-redlined *iff* entire fieldmark is
+    // Note: caller is responsible for checking for immediately adjacent hides
+    bool Next()
+    {
+        SwPosition const* pNextRedlineHide(nullptr);
+        assert(m_pEndPos);
+        if (m_isHideRedlines)
+        {
+            // position on current or next redline
+            for (; m_RedlineIndex < m_rIDRA.GetRedlineTable().size(); 
++m_RedlineIndex)
+            {
+                SwRangeRedline const*const pRed = 
m_rIDRA.GetRedlineTable()[m_RedlineIndex];
+
+                if (m_pEndPos->nNode.GetIndex() < 
pRed->Start()->nNode.GetIndex())
+                    break;
+
+                if (pRed->GetType() != RedlineType::Delete)
+                    continue;
+
+                SwPosition const*const pStart(pRed->Start());
+                SwPosition const*const pEnd(pRed->End());
+                if (*pStart == *pEnd)
+                {   // only allowed while moving (either way?)
+//                  
assert(IDocumentRedlineAccess::IsHideChanges(rIDRA.GetRedlineFlags()));
+                    continue;
+                }
+                if (pStart->nNode.GetNode().IsTableNode())
+                {
+                    assert(pEnd->nNode == m_Start.nNode && 
pEnd->nContent.GetIndex() == 0);
+                    continue; // known pathology, ignore it
+                }
+                if (*m_pEndPos <= *pStart)
+                {
+                    pNextRedlineHide = pStart;
+                    break; // the next one
+                }
+            }
+        }
+
+        // position on current or next fieldmark
+        m_oNextFieldmarkHide.reset();
+        if (m_eFieldmarkMode != sw::FieldmarkMode::ShowBoth)
+        {
+            sal_Unicode const magic(m_eFieldmarkMode == 
sw::FieldmarkMode::ShowResult
+                    ? CH_TXT_ATR_FIELDSTART
+                    : CH_TXT_ATR_FIELDSEP);
+            sal_Int32 const 
nPos(m_pEndPos->nNode.GetNode().GetTextNode()->GetText().indexOf(
+                    magic, m_pEndPos->nContent.GetIndex()));
+            if (nPos != -1)
+            {
+                
m_oNextFieldmarkHide.emplace(*m_pEndPos->nNode.GetNode().GetTextNode(), nPos);
+                sw::mark::IFieldmark const*const pFieldmark(
+                        m_eFieldmarkMode == sw::FieldmarkMode::ShowResult
+                            ? m_rIDMA.getFieldmarkAt(*m_oNextFieldmarkHide)
+                            : m_rIDMA.getFieldmarkFor(*m_oNextFieldmarkHide));
+                assert(pFieldmark);
+                m_Fieldmark.first = pFieldmark;
+                // for cursor travelling, there should be 2 visible chars;
+                // whichever char is hidden, the cursor travelling needs to
+                // be adapted in any case to skip in some situation or other;
+                // always hide the CH_TXT_ATR_FIELDSEP for now
+                if (m_eFieldmarkMode == sw::FieldmarkMode::ShowResult)
+                {
+                    m_Fieldmark.second.reset(
+                        new 
SwPosition(sw::mark::FindFieldSep(*m_Fieldmark.first)));
+                    ++m_Fieldmark.second->nContent;
+                    ++m_oNextFieldmarkHide->nContent; // skip start
+                }
+                else
+                {
+                    m_Fieldmark.second.reset(
+                        new SwPosition(pFieldmark->GetMarkEnd()));
+                    --m_Fieldmark.second->nContent;
+                }
+            }
+        }
+
+        // == can happen only if redline starts inside field command, and in
+        // that case redline will end before field separator
+        assert(!pNextRedlineHide || !m_oNextFieldmarkHide
+            || *pNextRedlineHide != *m_oNextFieldmarkHide
+            || *m_rIDRA.GetRedlineTable()[m_RedlineIndex]->End() < 
*m_Fieldmark.second);
+        if (pNextRedlineHide
+            && (!m_oNextFieldmarkHide || *pNextRedlineHide < 
*m_oNextFieldmarkHide))
+        {
+            SwRangeRedline const*const 
pRed(m_rIDRA.GetRedlineTable()[m_RedlineIndex]);
+            m_pStartPos = pRed->Start();
+            m_pEndPos = pRed->End();
+            ++m_RedlineIndex;
+            return true;
+        }
+        else if (m_oNextFieldmarkHide)
+        {
+            assert(!pNextRedlineHide || *m_oNextFieldmarkHide < 
*pNextRedlineHide);
+            m_pStartPos = &*m_oNextFieldmarkHide;
+            m_pEndPos = m_Fieldmark.second.get();
+            return true;
+        }
+        else // nothing
+        {
+            assert(!pNextRedlineHide && !m_oNextFieldmarkHide);
+            m_pStartPos = nullptr;
+            m_pEndPos = nullptr;
+            return false;
+        }
+    }
+};
+
+}
+
 namespace sw {
 
 std::unique_ptr<sw::MergedPara>
 CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
        FrameMode const eMode)
 {
-    IDocumentRedlineAccess const& rIDRA = 
rTextNode.getIDocumentRedlineAccess();
-    if (!rFrame.getRootFrame()->IsHideRedlines())
+    if (!rFrame.getRootFrame()->HasMergedParas())
     {
         return nullptr;
     }
@@ -67,29 +217,12 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & 
rTextNode,
     SwTextNode * pParaPropsNode(nullptr);
     SwTextNode * pNode(&rTextNode);
     sal_Int32 nLastEnd(0);
-    for (auto i = rIDRA.GetRedlinePos(rTextNode, RedlineType::Any);
-         i < rIDRA.GetRedlineTable().size(); ++i)
+    for (auto iter = HideIterator(rTextNode,
+                rFrame.getRootFrame()->IsHideRedlines(),
+                rFrame.getRootFrame()->GetFieldmarkMode()); iter.Next(); )
     {
-        SwRangeRedline const*const pRed = rIDRA.GetRedlineTable()[i];
-
-        if (pNode->GetIndex() < pRed->Start()->nNode.GetIndex())
-            break;
-
-        if (pRed->GetType() != RedlineType::Delete)
-            continue;
-
-        SwPosition const*const pStart(pRed->Start());
-        SwPosition const*const pEnd(pRed->End());
-        if (*pStart == *pEnd)
-        {   // only allowed while moving (either way?)
-//            
assert(IDocumentRedlineAccess::IsHideChanges(rIDRA.GetRedlineFlags()));
-            continue;
-        }
-        if (pStart->nNode.GetNode().IsTableNode())
-        {
-            assert(&pEnd->nNode.GetNode() == &rTextNode && 
pEnd->nContent.GetIndex() == 0);
-            continue; // known pathology, ignore it
-        }
+        SwPosition const*const pStart(iter.GetStartPos());
+        SwPosition const*const pEnd(iter.GetEndPos());
         bHaveRedlines = true;
         assert(pNode != &rTextNode || &pStart->nNode.GetNode() == &rTextNode); 
// detect calls with wrong start node
         if (pStart->nContent != nLastEnd) // not 0 so we eliminate adjacent 
deletes
commit c33c0a16ec781926b752f0589e6eca6f4e63a1e3
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Nov 17 12:43:03 2020 +0100
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Tue Nov 17 22:19:15 2020 +0100

    sw_fieldmarkhide: replace IsHideRedlines() with HasMergedParas()
    
    ... in wsfrm.cxx
    
    Change-Id: Iaa552f2527d47f475165a3f9da073052fc76ac51
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105983
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index ae9242cbd13e..438eaaef79fd 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4322,7 +4322,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
             auto eMode(sw::FrameMode::Existing);
             for (SwTextFrame * pFrame : frames)
             {
-                if (rLayout.IsHideRedlines())
+                if (rLayout.HasMergedParas())
                 {
                     assert(!pFrame->GetMergedPara() ||
                         !rNode.IsCreateFrameWhenHidingRedlines());
@@ -4435,7 +4435,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
         }
         if (!rNode.IsCreateFrameWhenHidingRedlines())
         {
-            if (rLayout.IsHideRedlines())
+            if (rLayout.HasMergedParas())
             {
                 if (rNode.IsContentNode())
                 {
@@ -4548,14 +4548,14 @@ static void UnHide(SwRootFrame & rLayout)
     std::set<sal_uLong> skippedFlys;
     UnHideRedlinesExtras(rLayout, rNodes, rNodes.GetEndOfAutotext(),
         // when un-hiding, delay all fly frame creation to AppendAllObjs below
-                         rLayout.IsHideRedlines() ? &skippedFlys : nullptr);
+                         rLayout.HasMergedParas() ? &skippedFlys : nullptr);
     // Footnotes are created automatically (after invalidation etc.) by
     // ConnectFootnote(), but need to be deleted manually. Footnotes do not
     // occur in flys or headers/footers.
     UnHideRedlinesExtras(rLayout, rNodes, rNodes.GetEndOfInserts(), nullptr);
     UnHideRedlines(rLayout, rNodes, rNodes.GetEndOfContent(), nullptr);
 
-    if (!rLayout.IsHideRedlines())
+    if (!rLayout.HasMergedParas())
     {   // create all previously hidden flys at once:
         // * Flys on first node of pre-existing merged frames that are hidden
         //   (in delete redline), to be added to the existing frame
@@ -4608,7 +4608,7 @@ static void UnHide(SwRootFrame & rLayout)
 
     // update SwPostItMgr / notes in the margin
     // note: as long as all shells share layout, broadcast to all shells!
-    rDoc.GetDocShell()->Broadcast( SwFormatFieldHint(nullptr, 
rLayout.IsHideRedlines()
+    rDoc.GetDocShell()->Broadcast( SwFormatFieldHint(nullptr, 
rLayout.HasMergedParas()
             ? SwFormatFieldHintWhich::REMOVED
             : SwFormatFieldHintWhich::INSERTED) );
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to