related tdf#158031 editeng: GetFieldAtSel...(+look before cursor)
Nearly a No-Functional-Change, but not quite.
For practical and intentional purposes, it can be considered NFC.
Although I didn't find an actual case where it happened,
a code read says SelectFieldAtCursor COULD select a non-field.
It assumed that previous code had already identified that there
must be a field here.
Well, I want to extend GetFieldAtSelection to check backwards
to solve bug 158031 anyway, so I might as well "fix"
this assumption to only select a valid field.
This function REALLY depends on
GetFieldAtSelection working properly.
So, I put some asserts in to ensure that stays true.
Change-Id: Ie22945a418497511501b04df5e17071d977cbd5b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158855
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
index d73cb24..bfa98d1 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -1344,7 +1344,16 @@ const SvxFieldItem* EditView::GetFieldUnderMousePointer( sal_Int32& nPara, sal_I
return GetField( aPos, &nPara, &nPos );
}
const SvxFieldItem* EditView::GetFieldAtSelection() const
const SvxFieldItem* EditView::GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const
{
bool* pIsBeforeCursor = bAlsoCheckBeforeCursor ? &bAlsoCheckBeforeCursor : nullptr;
return GetFieldAtSelection(pIsBeforeCursor);
}
// If pIsBeforeCursor != nullptr, the position before the cursor will also be checked for a field
// and pIsBeforeCursor will return true if that fallback field is returned.
// If no field is returned, the value in pIsBeforeCursor is meaningless.
const SvxFieldItem* EditView::GetFieldAtSelection(bool* pIsBeforeCursor) const
{
// a field is a dummy character - so it cannot span nodes or be a selection larger than 1
EditSelection aSel( pImpEditView->GetEditSelection() );
@@ -1361,6 +1370,13 @@ const SvxFieldItem* EditView::GetFieldAtSelection() const
// Only when cursor is in font of field, no selection,
// or only selecting field
bool bAlsoCheckBeforeCursor = false;
if (pIsBeforeCursor)
{
*pIsBeforeCursor = false;
bAlsoCheckBeforeCursor = nMaxIndex == nMinIndex;
}
const SvxFieldItem* pFoundBeforeCursor = nullptr;
const CharAttribList::AttribsType& rAttrs = aSel.Min().GetNode()->GetCharAttribs().GetAttribs();
for (const auto& rAttr: rAttrs)
{
@@ -1369,34 +1385,43 @@ const SvxFieldItem* EditView::GetFieldAtSelection() const
DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr->GetItem()), "No FieldItem...");
if (rAttr->GetStart() == nMinIndex)
return static_cast<const SvxFieldItem*>(rAttr->GetItem());
// perhaps the cursor is behind the field?
if (nMinIndex && rAttr->GetStart() == nMinIndex - 1)
pFoundBeforeCursor = static_cast<const SvxFieldItem*>(rAttr->GetItem());
}
}
if (bAlsoCheckBeforeCursor)
{
*pIsBeforeCursor = /*(bool)*/pFoundBeforeCursor;
return pFoundBeforeCursor;
}
return nullptr;
}
void EditView::SelectFieldAtCursor()
{
const SvxFieldItem* pFieldItem = GetFieldAtSelection();
if (pFieldItem)
{
// Make sure the whole field is selected
ESelection aSel = GetSelection();
if (aSel.nStartPos == aSel.nEndPos)
{
aSel.nEndPos++;
SetSelection(aSel);
}
}
bool bIsBeforeCursor = false;
const SvxFieldItem* pFieldItem = GetFieldAtSelection(&bIsBeforeCursor);
if (!pFieldItem)
return;
// Make sure the whole field is selected
// A field is represented by a dummy character - so it cannot be a selection larger than 1
ESelection aSel = GetSelection();
if (aSel.nStartPos == aSel.nEndPos) // not yet selected
{
// Cursor probably behind the field - extend selection to select the field
ESelection aSel = GetSelection();
if (aSel.nStartPos > 0 && aSel.nStartPos == aSel.nEndPos)
if (bIsBeforeCursor)
{
aSel.nStartPos--;
SetSelection(aSel);
assert (aSel.nStartPos);
--aSel.nStartPos;
}
else
aSel.nEndPos++;
SetSelection(aSel);
}
else
assert(std::abs(aSel.nStartPos - aSel.nEndPos) == 1);
}
const SvxFieldData* EditView::GetFieldAtCursor() const
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 48019e3..4c18ac2 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -329,7 +329,10 @@ public:
const SvxFieldItem* GetFieldUnderMousePointer( sal_Int32& nPara, sal_Int32& nPos ) const;
const SvxFieldItem* GetField( const Point& rPos, sal_Int32* pnPara = nullptr, sal_Int32* pnPos = nullptr ) const;
const SvxFieldItem* GetFieldAtSelection() const;
/// return the selected field or the field immediately after (or before) the current cursor
const SvxFieldItem* GetFieldAtSelection(bool bAlsoCheckBeforeCursor = false) const;
const SvxFieldItem* GetFieldAtSelection(bool* pIsBeforeCursor) const;
/// Select and return the field at the current cursor position
const SvxFieldData* GetFieldAtCursor() const;
void SelectFieldAtCursor();