summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-01-19 12:10:35 +0100
committerXisco Fauli <xiscofauli@libreoffice.org>2022-01-19 20:19:43 +0100
commitded965e82b11f527376bb9c2e7157288cbd08499 (patch)
tree0f2c34ac2f92213fb28a92b3a35a776e6a5764ef
parentsw_fieldmarkhide: disable layout cache if there are fieldmarks (diff)
downloadcore-ded965e82b11f527376bb9c2e7157288cbd08499.tar.gz
core-ded965e82b11f527376bb9c2e7157288cbd08499.zip
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.stahl@allotropia.de> (cherry picked from commit ab6176e88f78d0b3aa2490fbc7858304c2d4a437) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128537 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--sw/source/core/txtnode/modeltoviewhelper.cxx95
1 files changed, 95 insertions, 0 deletions
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;