sw/source/core/txtnode/modeltoviewhelper.cxx |   95 +++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

New commits:
commit d521502c4a47a407b071ff367e23b29d0dff33ce
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jan 19 12:10:35 2022 +0100
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Wed Jan 26 14:37:19 2022 +0100

    tdf#139638 sw_fieldmarkhide: hide fieldmark command in ModelToViewHelper
    
    The crash happened because the generated ToX text contained CH_TXTATR
    but the fieldmarks themselves were not copied.
    
    Just filter everything except the result of the fieldmark.
    
    Change-Id: I349e7793987624e64f5afe08dfa2ca977368156b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128605
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit ab6176e88f78d0b3aa2490fbc7858304c2d4a437)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128537
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128634
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    Tested-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/sw/source/core/txtnode/modeltoviewhelper.cxx 
b/sw/source/core/txtnode/modeltoviewhelper.cxx
index c8c6095726cb..a5ae25962862 100644
--- a/sw/source/core/txtnode/modeltoviewhelper.cxx
+++ b/sw/source/core/txtnode/modeltoviewhelper.cxx
@@ -31,7 +31,9 @@
 #include <txtftn.hxx>
 #include <scriptinfo.hxx>
 #include <IDocumentMarkAccess.hxx>
+#include <bookmark.hxx>
 #include <o3tl/sorted_vector.hxx>
+#include <deque>
 #include <vector>
 
 namespace {
@@ -104,6 +106,99 @@ ModelToViewHelper::ModelToViewHelper(const SwTextNode 
&rNode,
     if (eMode & ExpandMode::HideDeletions)
         SwScriptInfo::selectRedLineDeleted(rNode, aHiddenMulti);
 
+    if (eMode & ExpandMode::ExpandFields)
+    {
+        // hide fieldmark commands
+        IDocumentMarkAccess const& 
rIDMA(*rNode.GetDoc().getIDocumentMarkAccess());
+        ::std::deque<::std::pair<sw::mark::IFieldmark const*, bool>> 
startedFields;
+        SwPaM cursor(rNode, 0);
+        while (true)
+        {
+            sw::mark::IFieldmark const* pFieldMark(nullptr);
+            while (true) // loop to skip NonTextFieldmarks, those are handled 
later
+            {
+                pFieldMark = rIDMA.getFieldmarkFor(*cursor.GetPoint());
+                if (pFieldMark == nullptr
+                    || 
pFieldMark->GetMarkStart().nNode.GetNode().GetTextNode()->GetText()[
+                            pFieldMark->GetMarkStart().nContent.GetIndex()]
+                        != CH_TXT_ATR_FORMELEMENT)
+                {
+                    break;
+                }
+                pFieldMark = nullptr;
+                if (!cursor.Move(fnMoveBackward, GoInContent))
+                {
+                    break;
+                }
+            }
+            if (!pFieldMark)
+            {
+                break;
+            }
+            
assert(pFieldMark->GetMarkStart().nNode.GetNode().GetTextNode()->GetText()[pFieldMark->GetMarkStart().nContent.GetIndex()]
 != CH_TXT_ATR_FORMELEMENT);
+            // getFieldmarkFor may also return one that starts at rNode,0 -
+            // skip it, must be handled in loop below
+            if (pFieldMark->GetMarkStart().nNode < rNode)
+            {
+                SwPosition const sepPos(::sw::mark::FindFieldSep(*pFieldMark));
+                startedFields.emplace_front(pFieldMark, sepPos.nNode < rNode);
+                *cursor.GetPoint() = pFieldMark->GetMarkStart();
+            }
+            if (!cursor.Move(fnMoveBackward, GoInContent))
+            {
+                break;
+            }
+        }
+        ::std::optional<sal_Int32> oStartHidden;
+        if (!::std::all_of(startedFields.begin(), startedFields.end(),
+                    [](auto const& it) { return it.second; }))
+        {
+            oStartHidden.emplace(0); // node starts out hidden as field command
+        }
+        for (sal_Int32 i = 0; i < rNode.GetText().getLength(); ++i)
+        {
+            switch (rNode.GetText()[i])
+            {
+                case CH_TXT_ATR_FIELDSTART:
+                {
+                    auto const 
pFieldMark(rIDMA.getFieldmarkAt(SwPosition(const_cast<SwTextNode&>(rNode), i)));
+                    assert(pFieldMark);
+                    startedFields.emplace_back(pFieldMark, false);
+                    if (!oStartHidden)
+                    {
+                        oStartHidden.emplace(i);
+                    }
+                    break;
+                }
+                case CH_TXT_ATR_FIELDSEP:
+                {
+                    
assert(startedFields.back().first->IsCoveringPosition(SwPosition(const_cast<SwTextNode&>(rNode),
 i)));
+                    startedFields.back().second = true;
+                    assert(oStartHidden);
+                    if (::std::all_of(startedFields.begin(), 
startedFields.end(),
+                            [](auto const& it) { return it.second; }))
+                    {
+                        // i is still hidden but the Range end is oddly "-1"
+                        aHiddenMulti.Select({*oStartHidden, i}, true);
+                        oStartHidden.reset();
+                    }
+                    break;
+                }
+                case CH_TXT_ATR_FIELDEND:
+                {
+                    assert(startedFields.back().first == 
rIDMA.getFieldmarkAt(SwPosition(const_cast<SwTextNode&>(rNode), i)));
+                    startedFields.pop_back();
+                    aHiddenMulti.Select({i, i}, true);
+                    break;
+                }
+            }
+        }
+        if (oStartHidden && rNode.Len() != 0)
+        {
+            aHiddenMulti.Select({*oStartHidden, rNode.Len() - 1}, true);
+        }
+    }
+
     std::vector<block> aBlocks;
 
     sal_Int32 nShownStart = 0;

Reply via email to