[Libreoffice-commits] core.git: Branch 'private/mst/sw_fieldmarkhide' - 4 commits - sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Thu Nov 5 19:47:46 UTC 2020


Rebased ref, commits from common ancestor:
commit b0a715b849b38f6badbe6653e882016e8b85e231
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Nov 3 22:07:24 2020 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Nov 5 20:45:38 2020 +0100

    WIP draft
    
    Change-Id: I1e059c41ad0c82fa3d7c17ab324b87fc3b840861

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index fd3cb4a30677..5ab411897ffd 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4306,10 +4306,11 @@ 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());
+// nope: now switching from one mergedpara to different one
+//                    assert(!pFrame->GetMergedPara() ||
+//                        !rNode.IsCreateFrameWhenHidingRedlines());
                     if (rNode.IsCreateFrameWhenHidingRedlines())
                     {
                         {
@@ -4417,9 +4418,12 @@ static void UnHideRedlines(SwRootFrame & rLayout,
                 rNode.GetTableNode()->DelFrames(&rLayout);
             }
         }
+#if 1
+        // at this point it's false but it has no frames...
         if (!rNode.IsCreateFrameWhenHidingRedlines())
+#endif
         {
-            if (rLayout.IsHideRedlines())
+            if (rLayout.HasMergedParas())
             {
                 if (rNode.IsContentNode())
                 {
commit b006e31402ef5b69418debb2ebc98504255f738b
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Nov 5 20:28:06 2020 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Nov 5 20:45:38 2020 +0100

    SwCursor::LeftRight()
    
    Change-Id: Iff6680249dfe66d6d5b1a39c4543b51a5238b075

diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 78b85050a9e0..4d95fb1b5394 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1783,6 +1783,20 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
             beforeIndex = pFrame->MapModelToViewPos(*GetPoint());
         }
 
+        if (!bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowResult)
+        {
+            SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
+            assert(pNode);
+            if (pNode->Len() != GetPoint()->nContent.GetIndex()
+                && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDSTART)
+            {
+                IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess());
+                sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint()));
+                assert(pMark);
+                *GetPoint() = sw::mark::FindFieldSep(*pMark);
+            }
+        }
+
         if ( !Move( fnMove, fnGo ) )
             break;
 
@@ -1813,6 +1827,20 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
             }
         }
 
+        if (bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowCommand)
+        {
+            SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
+            assert(pNode);
+            if (pNode->Len() != GetPoint()->nContent.GetIndex()
+                && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDEND)
+            {
+                IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess());
+                sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint()));
+                assert(pMark);
+                *GetPoint() = sw::mark::FindFieldSep(*pMark);
+            }
+        }
+
         if (isFieldNames)
         {
             SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
commit fd5edc7a1c22169e7a6454589cdaa7f4326529da
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Nov 3 22:06:52 2020 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Nov 5 20:45:38 2020 +0100

    SwViewShell::ImplApplyViewOptions()
    
    Change-Id: Ie7b41048fe6c222272b345995fcdca4129be8ef0

diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index cac98fffaace..c7cebf5658ac 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -2187,9 +2187,16 @@ void SwViewShell::ImplApplyViewOptions( const SwViewOption &rOpt )
     // - fieldnames apply or not ...
     // ( - SwEndPortion must _no_ longer be generated. )
     // - Of course, the screen is something completely different than the printer ...
-    bReformat = bReformat || mpOpt->IsFieldName() != rOpt.IsFieldName();
     bool const isEnableFieldNames(mpOpt->IsFieldName() != rOpt.IsFieldName() && rOpt.IsFieldName());
 
+    if (mpOpt->IsFieldName() != rOpt.IsFieldName())
+    {
+        GetLayout()->SetFieldmarkMode( rOpt.IsFieldName()
+                    ? sw::FieldmarkMode::ShowCommand
+                    : sw::FieldmarkMode::ShowResult );
+        bReformat = true;
+    }
+
     // The map mode is changed, minima/maxima will be attended by UI
     if( mpOpt->GetZoom() != rOpt.GetZoom() && !IsPreview() )
     {
commit 7d57ac441114cf9399196416ac4ac78ee04b2800
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Nov 3 22:11:59 2020 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Nov 5 20:45:37 2020 +0100

    CheckParaRedlineMerge
    
    Change-Id: I4c6eac864da4b4bf531437e555a3994fd2670367

diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index b878f26e27f5..33b55600e30a 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,211 @@
 
 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(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
+    bool Next(/*SwTextNode const* pNode, sal_Int32 */)
+    {
+        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 (pNode->GetIndex() < pRed->Start()->nNode.GetIndex())
+                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
+                }
+                // TODO?
+                if (*m_pEndPos <= *pStart)
+                {
+                    pNextRedlineHide = pStart;
+                    break; // the next one
+                }
+                //m_pStartPos = pStart;
+                //m_pEndPos = pEnd;
+            }
+        }
+
+        // how to iterate ... m_pSepPos + pFM for the start / end ?
+        // position on current or next fieldmark
+        //SwPosition const* pNextFieldmarkHide(nullptr);
+        std::optional<SwPosition> oNextFieldmarkHide;
+        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 0
+            sal_Int32 nPos = pNode->GetText().indexOf(magic,
+                    m_Fieldmark.first
+                        ? HideCommand
+                            ? m_Fieldmark.first->GetEndPos()
+                            : *m_Fieldmark.second
+                        : 0);
+#endif
+            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;
+#if 1
+                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;
+                }
+#endif
+#if 0
+                ++m_oNextFieldmarkHide->nContent; // skip
+                if (m_eFieldmarkMode == sw::FieldmarkMode::ShowCommand)
+                {
+                    m_Fieldmark.second.reset(
+                        new SwPosition(pFieldmark->GetMarkEnd()));
+                }
+                else
+                {
+                    m_Fieldmark.second.reset(
+                        new SwPosition(sw::mark::FindFieldSep(*m_Fieldmark.first)));
+                    ++m_Fieldmark.second->nContent;
+                }
+                m_Fieldmark.second.reset(new SwPosition(
+                    m_eFieldmarkMode == sw::FieldmarkMode::ShowCommand
+                        ? pFieldmark->GetMarkEnd() - 1
+                        : sw::mark::FindFieldSep(*m_Fieldmark.first)));
+#endif
+    //WRONG NODe            assert(m_pEndPos->nNode.GetNode().GetTextNode()->GetNext()[m_Fieldmark.second] == CH_TXTATR_BREAKWORD);
+                //pNextFieldmarkHide = &tmp; /// FIXME UAF
+                // FIXME2: hide the sep? or the start? or none?
+                // ... how does cursor travel work? there should be just 2 visible fieldchar...
+                // ... MapViewToModel end-biased -> hide char at end?
+                // ... actually it doesn't matter: hide at the end and cursor moves in at the start; hide at the start and cursor moves in at the end
+                // ... BUT what about start at start of para / end at end of para ...
+                //     want to have pos. outside + pos. inside => always hide SEP?
+                // FIXME3: in case the start char is hidden -> must merge with prev redline?
+                //                     end                  ->                 next
+                //         NO - CheckParaRedlineMerge already merges
+            }
+        }
+
+            // the = case may depend on which CH is hidden ?
+        if (pNextRedlineHide
+            //&& (!pNextFieldmarkHide || *pNextRedlineHide <= *pNextFieldmarkHide))
+            && (!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 (pNextFieldmarkHide)
+        else if (m_oNextFieldmarkHide)
+        {
+            //assert(!pNextRedlineHide || *pNextFieldmarkHide < *pNextRedlineHide);
+            assert(!pNextRedlineHide || *m_oNextFieldmarkHide < *pNextRedlineHide);
+            // ??? how to iterate vs not
+            //m_pStartPos = pNextFieldmarkHide; // FIXME UAF
+            m_pStartPos = &*m_oNextFieldmarkHide;
+#if 0
+            m_pEndPos = m_eFieldmarkMode == sw::FieldmarkMode::ShowResult
+                ? m_Fieldmark.second.get()
+                : &m_Fieldmark.first->GetMarkEnd();
+#else
+            m_pEndPos = m_Fieldmark.second.get();
+#endif
+            return true;
+        }
+        else // nothing
+        {
+            //assert(!pNextRedlineHide && !pNextFieldmarkHide);
+            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())
+//    IDocumentRedlineAccess const& rIDRA = rTextNode.getIDocumentRedlineAccess();
+    if (!rFrame.getRootFrame()->HasMergedParas())
     {
         return nullptr;
     }
@@ -67,6 +267,11 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
     SwTextNode * pParaPropsNode(nullptr);
     SwTextNode * pNode(&rTextNode);
     sal_Int32 nLastEnd(0);
+    for (auto iter = HideIterator(rTextNode,
+                rFrame.getRootFrame()->IsHideRedlines(),
+                rFrame.getRootFrame()->GetFieldmarkMode()); iter.Next(); )
+    {
+#if 0
     for (auto i = rIDRA.GetRedlinePos(rTextNode, RedlineType::Any);
          i < rIDRA.GetRedlineTable().size(); ++i)
     {
@@ -90,6 +295,9 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
             assert(&pEnd->nNode.GetNode() == &rTextNode && pEnd->nContent.GetIndex() == 0);
             continue; // known pathology, ignore it
         }
+#endif
+        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


More information about the Libreoffice-commits mailing list