diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-01-19 12:10:35 +0100 |
---|---|---|
committer | Christian Lohmaier <lohmaier+LibreOffice@googlemail.com> | 2022-01-26 14:37:19 +0100 |
commit | d521502c4a47a407b071ff367e23b29d0dff33ce (patch) | |
tree | 2ac02033d3df7648c2196d12b349706cda6d01fc | |
parent | 7f0bbbea121335dc7d9a97be88ec7803c3a90bb1 (diff) |
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>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128634
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Tested-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
-rw-r--r-- | sw/source/core/txtnode/modeltoviewhelper.cxx | 95 |
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; |