summaryrefslogtreecommitdiff
path: root/sw/source/core/crsr/crsrsh.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/crsr/crsrsh.cxx')
-rw-r--r--sw/source/core/crsr/crsrsh.cxx1096
1 files changed, 754 insertions, 342 deletions
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index e02b02b9c187..58aa478d4d43 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -17,7 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <memory>
+#include <config_wasm_strip.h>
+
#include <com/sun/star/text/XTextRange.hpp>
#include <hintids.hxx>
@@ -54,7 +55,8 @@
#include <unotextrange.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
-#include <IGrammarContact.hxx>
+#include <GrammarContact.hxx>
+#include <OnlineAccessibilityCheck.hxx>
#include <comphelper/flagguard.hxx>
#include <strings.hrc>
#include <IDocumentLayoutAccess.hxx>
@@ -72,11 +74,12 @@
#include <tabcol.hxx>
#include <wrtsh.hxx>
#include <undobj.hxx>
-#include <boost/property_tree/json_parser.hpp>
+#include <view.hxx>
#include <hints.hxx>
+#include <tools/json_writer.hxx>
+#include <redline.hxx>
using namespace com::sun::star;
-using namespace util;
/**
* Check if pCurrentCursor points into already existing ranges and delete those.
@@ -84,8 +87,7 @@ using namespace util;
*/
static void CheckRange( SwCursor* pCurrentCursor )
{
- const SwPosition *pStt = pCurrentCursor->Start(),
- *pEnd = pCurrentCursor->GetPoint() == pStt ? pCurrentCursor->GetMark() : pCurrentCursor->GetPoint();
+ auto [pStt, pEnd] = pCurrentCursor->StartEnd(); // SwPosition*
SwPaM *pTmpDel = nullptr,
*pTmp = pCurrentCursor->GetNext();
@@ -93,9 +95,7 @@ static void CheckRange( SwCursor* pCurrentCursor )
// Search the complete ring
while( pTmp != pCurrentCursor )
{
- const SwPosition *pTmpStt = pTmp->Start(),
- *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
- pTmp->GetMark() : pTmp->GetPoint();
+ auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition*
if( *pStt <= *pTmpStt )
{
if( *pEnd > *pTmpStt ||
@@ -169,7 +169,7 @@ void SwCursorShell::DestroyCursor()
* Simply returns the current shell cursor if there is no selection
* (HasSelection()).
*/
-SwPaM & SwCursorShell::CreateNewShellCursor()
+SwCursor & SwCursorShell::CreateNewShellCursor()
{
if (HasSelection())
{
@@ -182,29 +182,29 @@ SwPaM & SwCursorShell::CreateNewShellCursor()
* Return the current shell cursor
* @return - returns current `SwPaM` shell cursor
*/
-SwPaM & SwCursorShell::GetCurrentShellCursor()
+SwCursor & SwCursorShell::GetCurrentShellCursor()
{
return *GetCursor();
}
/**
* Return pointer to the current shell cursor
- * @return - returns pointer to current `SwPaM` shell cursor
+ * @return - returns pointer to current `SwCursor` shell cursor
*/
-SwPaM* SwCursorShell::GetCursor( bool bMakeTableCursor ) const
+SwCursor* SwCursorShell::GetCursor( bool bMakeTableCursor ) const
{
if( m_pTableCursor )
{
if( bMakeTableCursor && m_pTableCursor->IsCursorMovedUpdate() )
{
//don't re-create 'parked' cursors
- if( m_pTableCursor->GetPoint()->nNode.GetIndex() &&
- m_pTableCursor->GetMark()->nNode.GetIndex() )
+ if( m_pTableCursor->GetPoint()->GetNodeIndex() &&
+ m_pTableCursor->GetMark()->GetNodeIndex() )
{
- const SwContentNode* pCNd = m_pTableCursor->GetContentNode();
+ const SwContentNode* pCNd = m_pTableCursor->GetPointContentNode();
if( pCNd && pCNd->getLayoutFrame( GetLayout() ) )
{
- pCNd = m_pTableCursor->GetContentNode(false);
+ pCNd = m_pTableCursor->GetMarkContentNode();
if( pCNd && pCNd->getLayoutFrame( GetLayout() ) )
{
SwShellTableCursor* pTC = m_pTableCursor;
@@ -228,9 +228,9 @@ void SwCursorShell::StartAction()
if( !ActionPend() )
{
// save for update of the ribbon bar
- const SwNode& rNd = m_pCurrentCursor->GetPoint()->nNode.GetNode();
+ const SwNode& rNd = m_pCurrentCursor->GetPoint()->GetNode();
m_nCurrentNode = rNd.GetIndex();
- m_nCurrentContent = m_pCurrentCursor->GetPoint()->nContent.GetIndex();
+ m_nCurrentContent = m_pCurrentCursor->GetPoint()->GetContentIndex();
m_nCurrentNdTyp = rNd.GetNodeType();
if( rNd.IsTextNode() )
m_nLeftFramePos = SwCallLink::getLayoutFrame( GetLayout(), *rNd.GetTextNode(), m_nCurrentContent, true );
@@ -240,18 +240,13 @@ void SwCursorShell::StartAction()
SwViewShell::StartAction(); // to the SwViewShell
}
-void SwCursorShell::EndAction( const bool bIdleEnd, const bool DoSetPosX )
+void SwCursorShell::EndAction( const bool bIdleEnd )
{
- comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll());
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll());
bool bVis = m_bSVCursorVis;
- sal_uInt16 eFlags = SwCursorShell::CHKRANGE;
- if ( !DoSetPosX )
- eFlags |= SwCursorShell::UPDOWN;
-
-
// Idle-formatting?
- if( bIdleEnd && Imp()->GetRegion() )
+ if( bIdleEnd && Imp()->HasPaintRegion() )
{
m_pCurrentCursor->Hide();
}
@@ -277,6 +272,7 @@ void SwCursorShell::EndAction( const bool bIdleEnd, const bool DoSetPosX )
return;
}
+ sal_uInt16 eFlags = SwCursorShell::CHKRANGE;
if ( !bIdleEnd )
eFlags |= SwCursorShell::SCROLLWIN;
@@ -316,7 +312,7 @@ void SwCursorShell::EndCursorMove( const bool bIdleEnd )
#ifdef DBG_UTIL
OSL_ENSURE( m_nCursorMove, "EndCursorMove() without SttCursorMove()." );
#endif
- EndAction( bIdleEnd, true );
+ EndAction( bIdleEnd );
--m_nCursorMove;
#ifdef DBG_UTIL
if( !m_nCursorMove )
@@ -324,7 +320,7 @@ void SwCursorShell::EndCursorMove( const bool bIdleEnd )
#endif
}
-bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
+bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode nMode,
bool bVisualAllowed )
{
if( IsTableMode() )
@@ -350,13 +346,13 @@ bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
// 2. CASE: Cursor is at beginning of numbered paragraph. A move
// to the left will simply set the bInFrontOfLabel flag:
else if (bLeft
- && pShellCursor->GetPoint()->nNode.GetNode().IsTextNode()
+ && pShellCursor->GetPoint()->GetNode().IsTextNode()
&& static_cast<SwTextFrame const*>(
- pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->getLayoutFrame(GetLayout())
+ pShellCursor->GetPoint()->GetNode().GetTextNode()->getLayoutFrame(GetLayout())
)->MapModelToViewPos(*pShellCursor->GetPoint()) == TextFrameIndex(0)
&& !pShellCursor->IsInFrontOfLabel()
&& !pShellCursor->HasMark()
- && nullptr != (pTextNd = sw::GetParaPropsNode(*GetLayout(), pShellCursor->GetPoint()->nNode))
+ && nullptr != (pTextNd = sw::GetParaPropsNode(*GetLayout(), pShellCursor->GetPoint()->GetNode()))
&& pTextNd->HasVisibleNumberingOrBullet())
{
SetInFrontOfLabel( true );
@@ -395,12 +391,18 @@ void SwCursorShell::MarkListLevel( const OUString& sListId,
if (sListId == m_sMarkedListId && nListLevel == m_nMarkedListLevel)
return;
- if ( !m_sMarkedListId.isEmpty() )
- mxDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false );
-
- if ( !sListId.isEmpty() )
+ // Writer redraws the "marked" list with the field shading, if there
+ // is no field shading then the marked list would be redrawn for no
+ // visually identifiable reason, so skip the mark if field shadings
+ // are disabled.
+ const bool bVisuallyMarked(GetViewOptions()->IsFieldShadings());
+ if (bVisuallyMarked)
{
- mxDoc->MarkListLevel( sListId, nListLevel, true );
+ if ( !m_sMarkedListId.isEmpty() )
+ mxDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false );
+
+ if ( !sListId.isEmpty() )
+ mxDoc->MarkListLevel( sListId, nListLevel, true );
}
m_sMarkedListId = sListId;
@@ -410,7 +412,7 @@ void SwCursorShell::MarkListLevel( const OUString& sListId,
void SwCursorShell::UpdateMarkedListLevel()
{
SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(),
- GetCursor_()->GetPoint()->nNode);
+ GetCursor_()->GetPoint()->GetNode());
if ( !pTextNd )
return;
@@ -527,7 +529,7 @@ bool SwCursorShell::UpDown( bool bUp, sal_uInt16 nCnt )
if( !bTableMode )
eUpdateMode = static_cast<CursorFlag>(eUpdateMode
| SwCursorShell::UPDOWN | SwCursorShell::CHKRANGE);
- UpdateCursor( static_cast<sal_uInt16>(eUpdateMode) );
+ UpdateCursor( o3tl::narrowing<sal_uInt16>(eUpdateMode) );
}
}
return bRet;
@@ -551,8 +553,8 @@ bool SwCursorShell::LRMargin( bool bLeft, bool bAPI)
if ( bLeft && !bTableMode && bRet && bWasAtLM && !GetCursor_()->HasMark() )
{
- const SwTextNode * pTextNd = GetCursor_()->GetNode().GetTextNode();
- assert(sw::GetParaPropsNode(*GetLayout(), GetCursor_()->GetPoint()->nNode) == pTextNd);
+ const SwTextNode * pTextNd = GetCursor_()->GetPointNode().GetTextNode();
+ assert(sw::GetParaPropsNode(*GetLayout(), GetCursor_()->GetPoint()->GetNode()) == pTextNd);
if ( pTextNd && pTextNd->HasVisibleNumberingOrBullet() )
SetInFrontOfLabel( true );
}
@@ -595,43 +597,331 @@ bool SwCursorShell::SttEndDoc( bool bStt )
return bRet;
}
+const SwTableNode* SwCursorShell::IsCursorInTable() const
+{
+ if (m_pTableCursor && m_pTableCursor->GetSelectedBoxesCount())
+ { // find the table that has the selected boxes
+ return m_pTableCursor->GetSelectedBoxes()[0]->GetSttNd()->FindTableNode();
+ }
+ return m_pCurrentCursor->GetPointNode().FindTableNode();
+}
+
+// fun cases to consider:
+// * outermost table
+// - into para => SA/ESA
+// - into prev/next table => continue...
+// - no prev/next => done
+// * inner table
+// - into containing cell => SA/ESA
+// - into prev/next of containing cell
+// + into para
+// + into table nested in prev/next cell
+// - out of table -> as above
+// => iterate in one direction until a node is reached that is a parent or a sibling of a parent of the current table
+// - parent reached => SA/ESA depending
+// - not in parent but in *prev/next* sibling of outer cell => TrySelectOuterTable
+// - not in parent but in *prev/next* sibling of outer table => TrySelectOuterTable
+// => select-all cannot select a sequence of table with no para at same level; only 1 table
+// - no parent, no prev/next => TrySelectOuterTable
+
+bool SwCursorShell::MoveOutOfTable()
+{
+ SwPosition const point(*getShellCursor(false)->GetPoint());
+ SwPosition const mark(*getShellCursor(false)->GetMark());
+
+ for (auto const fnMove : {&fnMoveBackward, &fnMoveForward})
+ {
+ Push();
+ SwCursor *const pCursor(getShellCursor(false));
+
+ pCursor->Normalize(fnMove == &fnMoveBackward);
+ pCursor->DeleteMark();
+ SwTableNode const*const pTable(pCursor->GetPoint()->GetNode().FindTableNode());
+ assert(pTable);
+ while (MovePara(GoInContent, *fnMove))
+ {
+ SwStartNode const*const pBox(pCursor->GetPoint()->GetNode().FindTableBoxStartNode());
+ if (!pBox)
+ {
+ Pop(SwCursorShell::PopMode::DeleteStack);
+ return true; // moved to paragraph at top-level of text
+ }
+ if (pBox->GetIndex() < pTable->GetIndex()
+ && pTable->EndOfSectionIndex() < pBox->EndOfSectionIndex())
+ {
+ Pop(SwCursorShell::PopMode::DeleteStack);
+ return true; // pBox contains start position (pTable)
+ }
+ }
+
+ Pop(SwCursorShell::PopMode::DeleteCurrent);
+ // FIXME: Pop doesn't restore original cursor if nested tables
+ *getShellCursor(false)->GetPoint() = point;
+ getShellCursor(false)->SetMark();
+ *getShellCursor(false)->GetMark() = mark;
+ }
+ return false;
+}
+
+bool SwCursorShell::TrySelectOuterTable()
+{
+ assert(m_pTableCursor);
+ SwTableNode const& rInnerTable(*m_pTableCursor->GetPoint()->GetNode().FindTableNode());
+ SwNodes const& rNodes(rInnerTable.GetNodes());
+ SwTableNode const*const pOuterTable(rInnerTable.GetNodes()[rInnerTable.GetIndex()-1]->FindTableNode());
+ if (!pOuterTable)
+ {
+ return false;
+ }
+
+ // manually select boxes of pOuterTable
+ SwNodeIndex firstCell(*pOuterTable, +1);
+ SwNodeIndex lastCell(*rNodes[pOuterTable->EndOfSectionIndex()-1]->StartOfSectionNode());
+ SwSelBoxes aNew;
+ pOuterTable->GetTable().CreateSelection(&firstCell.GetNode(), &lastCell.GetNode(),
+ aNew, SwTable::SEARCH_NONE, false);
+ // set table cursor to 1st / last content which may be in inner table
+ SwContentNode* const pStart = SwNodes::GoNext(&firstCell);
+ assert(pStart); // must at least find the previous point node
+ lastCell = *lastCell.GetNode().EndOfSectionNode();
+ SwContentNode *const pEnd = SwNodes::GoPrevious(&lastCell);
+ assert(pEnd); // must at least find the previous point node
+ delete m_pTableCursor;
+ m_pTableCursor = new SwShellTableCursor(*this, SwPosition(*pStart, 0), Point(),
+ SwPosition(*pEnd, 0), Point());
+ m_pTableCursor->ActualizeSelection( aNew );
+ m_pTableCursor->IsCursorMovedUpdate(); // clear this so GetCursor() doesn't recreate our SwSelBoxes
+
+ // this will update m_pCurrentCursor based on m_pTableCursor
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+
+ return true;
+}
+
+/// find XText start node
+static SwStartNode const* FindTextStart(SwPosition const& rPos)
+{
+ SwStartNode const* pStartNode(rPos.GetNode().StartOfSectionNode());
+ while (pStartNode && (pStartNode->IsSectionNode() || pStartNode->IsTableNode()))
+ {
+ pStartNode = pStartNode->StartOfSectionNode();
+ }
+ return pStartNode;
+}
+
+static SwStartNode const* FindParentText(SwShellCursor const& rCursor)
+{
+ // find closest section containing both start and end - ignore Sections
+ SwStartNode const* pStartNode(FindTextStart(*rCursor.Start()));
+ SwEndNode const* pEndNode(FindTextStart(*rCursor.End())->EndOfSectionNode());
+ while (pStartNode->EndOfSectionNode()->GetIndex() < pEndNode->GetIndex())
+ {
+ pStartNode = pStartNode->StartOfSectionNode();
+ }
+ while (pStartNode->GetIndex() < pEndNode->StartOfSectionNode()->GetIndex())
+ {
+ pEndNode = pEndNode->StartOfSectionNode()->StartOfSectionNode()->EndOfSectionNode();
+ }
+ assert(pStartNode->EndOfSectionNode() == pEndNode);
+
+ return (pStartNode->IsSectionNode() || pStartNode->IsTableNode())
+ ? FindTextStart(SwPosition(*pStartNode))
+ : pStartNode;
+}
+
+bool SwCursorShell::MoveStartText()
+{
+ SwPosition const old(*m_pCurrentCursor->GetPoint());
+ SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false)));
+ assert(pStartNode);
+ SwTableNode const*const pTable(pStartNode->FindTableNode());
+ m_pCurrentCursor->GetPoint()->Assign(*pStartNode);
+ SwNodes::GoNext(m_pCurrentCursor->GetPoint());
+ while (m_pCurrentCursor->GetPoint()->GetNode().FindTableNode() != pTable
+ && (!pTable || pTable->GetIndex() < m_pCurrentCursor->GetPoint()->GetNode().FindTableNode()->GetIndex())
+ && MoveOutOfTable());
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return old != *m_pCurrentCursor->GetPoint();
+}
+
+// select all inside the current XText, with table or hidden para at start/end
void SwCursorShell::ExtendedSelectAll(bool bFootnotes)
{
+ // find common ancestor node of both ends of cursor
+ SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false)));
+ assert(pStartNode);
+ if (IsTableMode())
+ { // convert m_pTableCursor to m_pCurrentCursor after determining pStartNode
+ TableCursorToCursor();
+ }
SwNodes& rNodes = GetDoc()->GetNodes();
+ m_pCurrentCursor->Normalize(true);
SwPosition* pPos = m_pCurrentCursor->GetPoint();
- pPos->nNode = bFootnotes ? rNodes.GetEndOfPostIts() : rNodes.GetEndOfAutotext();
- pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
+ pPos->Assign(bFootnotes ? rNodes.GetEndOfPostIts() : static_cast<SwNode const&>(*pStartNode));
+ SwNodes::GoNext(pPos);
pPos = m_pCurrentCursor->GetMark();
- pPos->nNode = rNodes.GetEndOfContent();
- SwContentNode* pCNd = SwNodes::GoPrevious( &pPos->nNode );
- pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
+ pPos->Assign(bFootnotes ? rNodes.GetEndOfContent() : static_cast<SwNode const&>(*pStartNode->EndOfSectionNode()));
+ SwContentNode* pCNd = SwNodes::GoPrevious( pPos );
+ if (pCNd)
+ pPos->AssignEndIndex(*pCNd);
+}
+
+static typename SwCursorShell::StartsWith StartsWith(SwStartNode const& rStart)
+{
+ for (auto i = rStart.GetIndex() + 1; i < rStart.EndOfSectionIndex(); ++i)
+ {
+ SwNode const& rNode(*rStart.GetNodes()[i]);
+ switch (rNode.GetNodeType())
+ {
+ case SwNodeType::Section:
+ if (rNode.GetSectionNode()->GetSection().IsHidden())
+ return SwCursorShell::StartsWith::HiddenSection;
+ continue;
+ case SwNodeType::Table:
+ return SwCursorShell::StartsWith::Table;
+ case SwNodeType::Text:
+ if (rNode.GetTextNode()->IsHidden())
+ {
+ return SwCursorShell::StartsWith::HiddenPara;
+ }
+ return SwCursorShell::StartsWith::None;
+ default:
+ return SwCursorShell::StartsWith::None;
+ }
+ }
+ return SwCursorShell::StartsWith::None;
}
-bool SwCursorShell::ExtendedSelectedAll()
+static typename SwCursorShell::StartsWith EndsWith(SwStartNode const& rStart)
{
+ for (auto i = rStart.EndOfSectionIndex() - 1; rStart.GetIndex() < i; --i)
+ {
+ SwNode const& rNode(*rStart.GetNodes()[i]);
+ switch (rNode.GetNodeType())
+ {
+ case SwNodeType::End:
+ if (auto pStartNode = rNode.StartOfSectionNode(); pStartNode->IsTableNode())
+ {
+ return SwCursorShell::StartsWith::Table;
+ }
+ else if (pStartNode->IsSectionNode())
+ {
+ if (pStartNode->GetSectionNode()->GetSection().IsHidden())
+ return SwCursorShell::StartsWith::HiddenSection;
+ }
+ //TODO buggy SwUndoRedline in testTdf137503? assert(rNode.StartOfSectionNode()->IsSectionNode());
+ break;
+ case SwNodeType::Text:
+ if (rNode.GetTextNode()->IsHidden())
+ {
+ return SwCursorShell::StartsWith::HiddenPara;
+ }
+ return SwCursorShell::StartsWith::None;
+ default:
+ return SwCursorShell::StartsWith::None;
+ }
+ }
+ return SwCursorShell::StartsWith::None;
+}
+
+// return the node that is the start of the extended selection (to include table
+// or section start nodes; looks like extending for end nodes is not required)
+::std::optional<::std::pair<SwNode const*, ::std::vector<SwTableNode*>>>
+SwCursorShell::ExtendedSelectedAll() const
+{
+ if (m_pTableCursor)
+ {
+ return {};
+ }
+
SwNodes& rNodes = GetDoc()->GetNodes();
- SwNodeIndex nNode = rNodes.GetEndOfAutotext();
- SwContentNode* pStart = rNodes.GoNext(&nNode);
+ SwShellCursor const*const pShellCursor = getShellCursor(false);
+ SwStartNode const* pStartNode(FindParentText(*pShellCursor));
+
+ SwNodeIndex nNode(*pStartNode);
+ SwContentNode* pStart = SwNodes::GoNext(&nNode);
if (!pStart)
- return false;
+ {
+ return {};
+ }
- nNode = rNodes.GetEndOfContent();
+ nNode = *pStartNode->EndOfSectionNode();
SwContentNode* pEnd = SwNodes::GoPrevious(&nNode);
if (!pEnd)
- return false;
+ {
+ return {};
+ }
SwPosition aStart(*pStart, 0);
SwPosition aEnd(*pEnd, pEnd->Len());
- SwShellCursor* pShellCursor = getShellCursor(false);
- return aStart == *pShellCursor->Start() && aEnd == *pShellCursor->End();
+ if (!(aStart == *pShellCursor->Start() && aEnd == *pShellCursor->End()))
+ {
+ return {};
+ }
+
+ auto const ends(::EndsWith(*pStartNode));
+ if (::StartsWith(*pStartNode) == StartsWith::None
+ && ends == StartsWith::None)
+ {
+ return {}; // "ordinary" selection will work
+ }
+
+ ::std::vector<SwTableNode*> tablesAtEnd;
+ if (ends == StartsWith::Table)
+ {
+ SwNode * pLastNode(rNodes[pStartNode->EndOfSectionIndex() - 1]);
+ while (pLastNode->IsEndNode())
+ {
+ SwNode *const pNode(pLastNode->StartOfSectionNode());
+ if (pNode->IsTableNode())
+ {
+ tablesAtEnd.push_back(pNode->GetTableNode());
+ pLastNode = rNodes[pNode->GetIndex() - 1];
+ }
+ else if (pNode->IsSectionNode())
+ {
+ pLastNode = rNodes[pLastNode->GetIndex() - 1];
+ }
+ }
+ assert(!tablesAtEnd.empty());
+ }
+
+ // tdf#133990 ensure directly containing section is included in SwUndoDelete
+ while (pStartNode->IsSectionNode()
+ && pStartNode->GetIndex() == pStartNode->StartOfSectionNode()->GetIndex() + 1
+ && pStartNode->EndOfSectionNode()->GetIndex() + 1 == pStartNode->StartOfSectionNode()->EndOfSectionNode()->GetIndex())
+ {
+ pStartNode = pStartNode->StartOfSectionNode();
+ }
+
+ // pStartNode is the node that fully contains the selection - the first
+ // node of the selection is the first node inside pStartNode
+ return ::std::make_pair(rNodes[pStartNode->GetIndex() + 1], tablesAtEnd);
}
-bool SwCursorShell::StartsWithTable()
+typename SwCursorShell::StartsWith SwCursorShell::StartsWith_()
{
- SwNodes& rNodes = GetDoc()->GetNodes();
- SwNodeIndex nNode(rNodes.GetEndOfExtras());
- SwContentNode* pContentNode = rNodes.GoNext(&nNode);
- return pContentNode->FindTableNode();
+ SwShellCursor const*const pShellCursor = getShellCursor(false);
+ // first, check if this is invalid; ExtendedSelectAll(true) may result in
+ // a) an ordinary selection that is valid
+ // b) a selection that is extended
+ // c) a selection that is invalid and will cause FindParentText to loop
+ SwNode const& rEndOfExtras(GetDoc()->GetNodes().GetEndOfExtras());
+ if (pShellCursor->Start()->nNode.GetIndex() <= rEndOfExtras.GetIndex()
+ && rEndOfExtras.GetIndex() < pShellCursor->End()->nNode.GetIndex())
+ {
+ return StartsWith::None; // *very* extended, no ExtendedSelectedAll handling!
+ }
+ SwStartNode const*const pStartNode(FindParentText(*pShellCursor));
+ if (auto const ret = ::StartsWith(*pStartNode); ret != StartsWith::None)
+ {
+ return ret;
+ }
+ if (auto const ret = ::EndsWith(*pStartNode); ret != StartsWith::None)
+ {
+ return ret;
+ }
+ return StartsWith::None;
}
bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
@@ -647,7 +937,7 @@ bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
SwCursorSaveState aSaveState( *m_pCurrentCursor );
Point& rPt = m_pCurrentCursor->GetPtPos();
std::pair<Point, bool> tmp(rPt, false);
- SwContentFrame * pFrame = m_pCurrentCursor->GetContentNode()->
+ SwContentFrame * pFrame = m_pCurrentCursor->GetPointContentNode()->
getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint(), &tmp);
if( pFrame && GetFrameInPage( pFrame, fnWhichPage, fnPosPage, m_pCurrentCursor ) &&
!m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::Toggle |
@@ -660,21 +950,21 @@ bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
return bRet;
}
-bool SwCursorShell::isInHiddenTextFrame(SwShellCursor* pShellCursor)
+bool SwCursorShell::isInHiddenFrame(SwShellCursor* pShellCursor)
{
- SwContentNode *pCNode = pShellCursor->GetContentNode();
+ SwContentNode *pCNode = pShellCursor->GetPointContentNode();
std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false);
SwContentFrame *const pFrame = pCNode
? pCNode->getLayoutFrame(GetLayout(), pShellCursor->GetPoint(), &tmp)
: nullptr;
- return !pFrame || (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow());
+ return !pFrame || pFrame->IsHiddenNow();
}
// sw_redlinehide: this should work for all cases: GoCurrPara, GoNextPara, GoPrevPara
static bool IsAtStartOrEndOfFrame(SwCursorShell const*const pShell,
SwShellCursor const*const pShellCursor, SwMoveFnCollection const& fnPosPara)
{
- SwContentNode *const pCNode = pShellCursor->GetContentNode();
+ SwContentNode *const pCNode = pShellCursor->GetPointContentNode();
assert(pCNode); // surely can't have moved otherwise?
std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false);
SwContentFrame const*const pFrame = pCNode->getLayoutFrame(
@@ -708,7 +998,7 @@ bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const &
//which is what SwCursorShell::UpdateCursorPos will reset
//the position to if we pass it a position in an
//invisible hidden paragraph field
- while (isInHiddenTextFrame(pTmpCursor)
+ while (isInHiddenFrame(pTmpCursor)
|| !IsAtStartOrEndOfFrame(this, pTmpCursor, fnPosPara))
{
if (!pTmpCursor->MovePara(fnWhichPara, fnPosPara))
@@ -734,10 +1024,10 @@ bool SwCursorShell::MoveSection( SwWhichSection fnWhichSect,
// position cursor
-static SwFrame* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
+static SwFrame* lcl_IsInHeaderFooter( SwNode& rNd, Point& rPt )
{
SwFrame* pFrame = nullptr;
- SwContentNode* pCNd = rIdx.GetNode().GetContentNode();
+ SwContentNode* pCNd = rNd.GetContentNode();
if( pCNd )
{
std::pair<Point, bool> tmp(rPt, false);
@@ -755,13 +1045,13 @@ static SwFrame* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
bool SwCursorShell::IsInHeaderFooter( bool* pbInHeader ) const
{
Point aPt;
- SwFrame* pFrame = ::lcl_IsInHeaderFooter( m_pCurrentCursor->GetPoint()->nNode, aPt );
+ SwFrame* pFrame = ::lcl_IsInHeaderFooter( m_pCurrentCursor->GetPoint()->GetNode(), aPt );
if( pFrame && pbInHeader )
*pbInHeader = pFrame->IsHeaderFrame();
return nullptr != pFrame;
}
-int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
+int SwCursorShell::SetCursor(const Point& rLPt, bool bOnlyText, bool bBlock, bool bFieldInfo)
{
CurrShell aCurr( this );
@@ -772,8 +1062,10 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
SwCursorMoveState aTmpState( IsTableMode() ? CursorMoveState::TableSel :
bOnlyText ? CursorMoveState::SetOnlyText : CursorMoveState::NONE );
aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.m_bFieldInfo = bFieldInfo; // always set cursor at field-start if point is over field
+ aTmpState.m_bPosMatchesBounds = bFieldInfo; // always set cursor at character-start if over char
- SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode);
+ SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
if ( pTextNd && !IsTableMode() &&
// #i37515# No bInFrontOfLabel during selection
@@ -799,9 +1091,9 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
if( CursorMoveState::RightMargin == aTmpState.m_eState )
m_eMvState = CursorMoveState::RightMargin;
// is the new position in header or footer?
- SwFrame* pFrame = lcl_IsInHeaderFooter( aPos.nNode, aPt );
- if( IsTableMode() && !pFrame && aPos.nNode.GetNode().StartOfSectionNode() ==
- pCursor->GetPoint()->nNode.GetNode().StartOfSectionNode() )
+ SwFrame* pFrame = lcl_IsInHeaderFooter( aPos.GetNode(), aPt );
+ if( IsTableMode() && !pFrame && aPos.GetNode().StartOfSectionNode() ==
+ pCursor->GetPoint()->GetNode().StartOfSectionNode() )
// same table column and not in header/footer -> back
return bRet;
@@ -821,17 +1113,17 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
{
if( pFrame )
{
- if( pFrame->getFrameArea().IsInside( rCurrentCursorPt ))
+ if( pFrame->getFrameArea().Contains( rCurrentCursorPt ))
return bRet;
}
- else if( aPos.nNode.GetNode().IsContentNode() )
+ else if( aPos.GetNode().IsContentNode() )
{
// in the same frame?
std::pair<Point, bool> tmp(m_aCharRect.Pos(), false);
- SwFrame* pOld = static_cast<SwContentNode&>(aPos.nNode.GetNode()).getLayoutFrame(
+ SwFrame* pOld = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame(
GetLayout(), nullptr, &tmp);
tmp.first = aPt;
- SwFrame* pNew = static_cast<SwContentNode&>(aPos.nNode.GetNode()).getLayoutFrame(
+ SwFrame* pNew = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame(
GetLayout(), nullptr, &tmp);
if( pNew == pOld )
return bRet;
@@ -841,8 +1133,8 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
else
{
// SSelection over not allowed sections or if in header/footer -> different
- if( !CheckNodesRange( aPos.nNode, pCursor->GetMark()->nNode, true )
- || ( pFrame && !pFrame->getFrameArea().IsInside( pCursor->GetMkPos() ) ))
+ if( !CheckNodesRange( aPos.GetNode(), pCursor->GetMark()->GetNode(), true )
+ || ( pFrame && !pFrame->getFrameArea().Contains( pCursor->GetMkPos() ) ))
return bRet;
// is at same position but not in header/footer
@@ -999,7 +1291,7 @@ bool SwCursorShell::TestCurrPam(
// check if the SPoint is in a table selection
if( m_pTableCursor )
- return m_pTableCursor->IsInside( rPt );
+ return m_pTableCursor->Contains( rPt );
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
// search position <rPt> in document
@@ -1008,6 +1300,7 @@ bool SwCursorShell::TestCurrPam(
SwCursorMoveState aTmpState( CursorMoveState::NONE );
aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.m_bPosMatchesBounds = true; // treat last half of character same as first half
if ( !GetLayout()->GetModelPositionForViewPoint( &aPtPos, aPt, &aTmpState ) && bTstHit )
return false;
@@ -1058,7 +1351,7 @@ int SwCursorShell::CompareCursorStackMkCurrPt() const
{
int nRet = 0;
const SwPosition *pFirst = nullptr, *pSecond = nullptr;
- const SwPaM *pCur = GetCursor(), *pStack = m_pStackCursor;
+ const SwCursor *pCur = GetCursor(), *pStack = m_pStackCursor;
// cursor on stack is needed if we compare against stack
if( pStack )
{
@@ -1082,14 +1375,14 @@ bool SwCursorShell::IsSelOnePara() const
{
return false;
}
- if (m_pCurrentCursor->GetPoint()->nNode == m_pCurrentCursor->GetMark()->nNode)
+ if (m_pCurrentCursor->GetPoint()->GetNode() == m_pCurrentCursor->GetMark()->GetNode())
{
return true;
}
if (GetLayout()->HasMergedParas())
{
SwContentFrame const*const pFrame(GetCurrFrame(false));
- auto const n(m_pCurrentCursor->GetMark()->nNode.GetIndex());
+ auto const n(m_pCurrentCursor->GetMark()->GetNodeIndex());
return FrameContainsNode(*pFrame, n);
}
return false;
@@ -1099,7 +1392,7 @@ bool SwCursorShell::IsSttPara() const
{
if (GetLayout()->HasMergedParas())
{
- SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode());
+ SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode());
if (pNode)
{
SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
@@ -1111,14 +1404,14 @@ bool SwCursorShell::IsSttPara() const
}
}
}
- return m_pCurrentCursor->GetPoint()->nContent == 0;
+ return m_pCurrentCursor->GetPoint()->GetContentIndex() == 0;
}
bool SwCursorShell::IsEndPara() const
{
if (GetLayout()->HasMergedParas())
{
- SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode());
+ SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode());
if (pNode)
{
SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
@@ -1130,7 +1423,7 @@ bool SwCursorShell::IsEndPara() const
}
}
}
- return m_pCurrentCursor->GetPoint()->nContent == m_pCurrentCursor->GetContentNode()->Len();
+ return m_pCurrentCursor->GetPoint()->GetContentIndex() == m_pCurrentCursor->GetPointContentNode()->Len();
}
bool SwCursorShell::IsEndOfTable() const
@@ -1148,15 +1441,29 @@ bool SwCursorShell::IsEndOfTable() const
SwNodeIndex const lastNode(*pEndTableNode, -2);
SAL_WARN_IF(!lastNode.GetNode().GetTextNode(), "sw.core",
"text node expected");
- return (lastNode == m_pCurrentCursor->GetPoint()->nNode);
+ return (lastNode == m_pCurrentCursor->GetPoint()->GetNode());
}
bool SwCursorShell::IsCursorInFootnote() const
{
- SwStartNodeType aStartNodeType = m_pCurrentCursor->GetNode().StartOfSectionNode()->GetStartNodeType();
+ SwStartNodeType aStartNodeType = m_pCurrentCursor->GetPointNode().StartOfSectionNode()->GetStartNodeType();
return aStartNodeType == SwStartNodeType::SwFootnoteStartNode;
}
+Point SwCursorShell::GetCursorPagePos() const
+{
+ Point aRet(-1, -1);
+ if (SwFrame *pFrame = GetCurrFrame())
+ {
+ if (SwPageFrame* pCurrentPage = pFrame->FindPageFrame())
+ {
+ const Point& rDocPos = GetCursorDocPos();
+ aRet = rDocPos - pCurrentPage->getFrameArea().TopLeft();
+ }
+ }
+ return aRet;
+}
+
bool SwCursorShell::IsInFrontOfLabel() const
{
return m_pCurrentCursor->IsInFrontOfLabel();
@@ -1305,14 +1612,14 @@ OUString SwCursorShell::getPageRectangles()
OUStringBuffer aBuf;
for (const SwFrame* pFrame = pLayout->GetLower(); pFrame; pFrame = pFrame->GetNext())
{
- aBuf.append(pFrame->getFrameArea().Left());
- aBuf.append(", ");
- aBuf.append(pFrame->getFrameArea().Top());
- aBuf.append(", ");
- aBuf.append(pFrame->getFrameArea().Width());
- aBuf.append(", ");
- aBuf.append(pFrame->getFrameArea().Height());
- aBuf.append("; ");
+ aBuf.append(OUString::number(pFrame->getFrameArea().Left())
+ + ", "
+ + OUString::number(pFrame->getFrameArea().Top())
+ + ", "
+ + OUString::number(pFrame->getFrameArea().Width())
+ + ", "
+ + OUString::number(pFrame->getFrameArea().Height())
+ + "; ");
}
if (!aBuf.isEmpty())
aBuf.setLength( aBuf.getLength() - 2); // remove the last "; "
@@ -1394,7 +1701,7 @@ bool SwCursorShell::GoPrevCursor()
return true;
}
-bool SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext)
+void SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext)
{
SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
@@ -1402,15 +1709,18 @@ bool SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext)
{
if( !m_pCurrentCursor->HasMark() )
SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
- return false;
+ return;
}
- return bNext ? GoNextCursor() : GoPrevCursor();
+ if (bNext)
+ GoNextCursor();
+ else
+ GoPrevCursor();
}
void SwCursorShell::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect)
{
- comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll());
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll());
CurrShell aCurr( this );
// always switch off all cursors when painting
@@ -1418,7 +1728,7 @@ void SwCursorShell::Paint(vcl::RenderContext& rRenderContext, const tools::Recta
bool bVis = false;
// if a cursor is visible then hide the SV cursor
- if( m_pVisibleCursor->IsVisible() && !aRect.IsOver( m_aCharRect ) )
+ if( m_pVisibleCursor->IsVisible() && !aRect.Overlaps( m_aCharRect ) )
{
bVis = true;
m_pVisibleCursor->Hide();
@@ -1484,8 +1794,8 @@ void SwCursorShell::VisPortChgd( const SwRect & rRect )
/** Set the cursor back into content.
- This should only be called if the cursor was move somewhere else (e.g. when
- deleting a border). The new position is calculated from its current position
+ This should only be called if the cursor was moved (e.g. when deleting a
+ text frame). The new position is calculated from its current position
in the layout.
*/
void SwCursorShell::UpdateCursorPos()
@@ -1495,35 +1805,54 @@ void SwCursorShell::UpdateCursorPos()
SwShellCursor* pShellCursor = getShellCursor( true );
Size aOldSz( GetDocSize() );
- if( isInHiddenTextFrame(pShellCursor) )
+ if (isInHiddenFrame(pShellCursor) && !ExtendedSelectedAll())
{
- SwCursorMoveState aTmpState( CursorMoveState::NONE );
+ SwCursorMoveState aTmpState(CursorMoveState::SetOnlyText);
aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
GetLayout()->GetModelPositionForViewPoint( pShellCursor->GetPoint(), pShellCursor->GetPtPos(),
&aTmpState );
pShellCursor->DeleteMark();
+ // kde45196-1.html: try to get to a non-hidden paragraph, there must
+ // be one in the document body
+ while (isInHiddenFrame(pShellCursor))
+ {
+ if (!pShellCursor->MovePara(GoNextPara, fnParaStart))
+ {
+ break;
+ }
+ }
+ while (isInHiddenFrame(pShellCursor))
+ {
+ if (!pShellCursor->MovePara(GoPrevPara, fnParaStart))
+ {
+ break;
+ }
+ }
+ }
+ auto* pDoc = GetDoc();
+ if (pDoc)
+ {
+ pDoc->getGrammarContact()->updateCursorPosition(*m_pCurrentCursor->GetPoint());
+ pDoc->getOnlineAccessibilityCheck()->update(*m_pCurrentCursor->GetPoint());
}
- IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : nullptr;
- if( pGrammarContact )
- pGrammarContact->updateCursorPosition( *m_pCurrentCursor->GetPoint() );
+
--mnStartAction;
if( aOldSz != GetDocSize() )
SizeChgNotify();
}
// #i65475# - if Point/Mark in hidden sections, move them out
-static bool lcl_CheckHiddenSection( SwNodeIndex& rIdx )
+static bool lcl_CheckHiddenSection( SwPosition& rPos )
{
bool bOk = true;
- const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
+ const SwSectionNode* pSectNd = rPos.GetNode().FindSectionNode();
if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
{
- SwNodeIndex aTmp( *pSectNd );
const SwNode* pFrameNd =
- rIdx.GetNodes().FindPrvNxtFrameNode( aTmp, pSectNd->EndOfSectionNode() );
+ rPos.GetNodes().FindPrvNxtFrameNode( *pSectNd, pSectNd->EndOfSectionNode() );
bOk = pFrameNd != nullptr;
SAL_WARN_IF(!bOk, "sw.core", "found no Node with Frames");
- rIdx = aTmp;
+ rPos.Assign( *(bOk ? pFrameNd : pSectNd) );
}
return bOk;
}
@@ -1531,11 +1860,11 @@ static bool lcl_CheckHiddenSection( SwNodeIndex& rIdx )
/// Try to set the cursor to the next visible content node.
static void lcl_CheckHiddenPara( SwPosition& rPos )
{
- SwNodeIndex aTmp( rPos.nNode );
+ SwNodeIndex aTmp( rPos.GetNode() );
SwTextNode* pTextNd = aTmp.GetNode().GetTextNode();
while( pTextNd && pTextNd->HasHiddenCharAttribute( true ) )
{
- SwContentNode* pContent = aTmp.GetNodes().GoNext( &aTmp );
+ SwContentNode* pContent = SwNodes::GoNext(&aTmp);
if ( pContent && pContent->IsTextNode() )
pTextNd = pContent->GetTextNode();
else
@@ -1543,9 +1872,10 @@ static void lcl_CheckHiddenPara( SwPosition& rPos )
}
if ( pTextNd )
- rPos = SwPosition( aTmp, SwIndex( pTextNd, 0 ) );
+ rPos.Assign( *pTextNd, 0 );
}
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
namespace {
// #i27301# - helper class that notifies the accessibility about invalid text
@@ -1567,6 +1897,7 @@ class SwNotifyAccAboutInvalidTextSelections
};
}
+#endif
void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
{
@@ -1580,7 +1911,9 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
return; // if not then no update
}
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
+#endif
if ( m_bIgnoreReadonly )
{
@@ -1598,10 +1931,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
// then the table mode is active (also if it is already active: m_pTableCursor)
SwPaM* pTstCursor = getShellCursor( true );
if( pTstCursor->HasMark() && !m_pBlockCursor &&
- mxDoc->IsIdxInTable( pTstCursor->GetPoint()->nNode ) &&
+ SwDoc::IsInTable( pTstCursor->GetPoint()->GetNode() ) &&
( m_pTableCursor ||
- pTstCursor->GetNode().StartOfSectionNode() !=
- pTstCursor->GetNode( false ).StartOfSectionNode() ) && !mbSelectAll)
+ pTstCursor->GetPointNode().StartOfSectionNode() !=
+ pTstCursor->GetMarkNode().StartOfSectionNode() ) && !mbSelectAll)
{
SwShellCursor* pITmpCursor = getShellCursor( true );
Point aTmpPt( pITmpCursor->GetPtPos() );
@@ -1609,8 +1942,8 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
SwPosition* pPos = pITmpCursor->GetPoint();
// Bug 65475 (1999) - if Point/Mark in hidden sections, move them out
- lcl_CheckHiddenSection( pPos->nNode );
- lcl_CheckHiddenSection( pITmpCursor->GetMark()->nNode );
+ lcl_CheckHiddenSection( *pPos );
+ lcl_CheckHiddenSection( *pITmpCursor->GetMark() );
// Move cursor out of hidden paragraphs
if ( !GetViewOptions()->IsShowHiddenChar() )
@@ -1620,7 +1953,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
}
std::pair<Point, bool> const tmp(aTmpPt, false);
- SwContentFrame *pTableFrame = pPos->nNode.GetNode().GetContentNode()->
+ SwContentFrame *pTableFrame = pPos->GetNode().GetContentNode()->
getLayoutFrame( GetLayout(), pPos, &tmp);
OSL_ENSURE( pTableFrame, "Table Cursor not in Content ??" );
@@ -1638,7 +1971,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
if ( !bInRepeatedHeadline )
{
std::pair<Point, bool> const tmp1(aTmpMk, false);
- SwContentFrame* pMarkTableFrame = pITmpCursor->GetContentNode( false )->
+ SwContentFrame* pMarkTableFrame = pITmpCursor->GetMarkContentNode()->
getLayoutFrame(GetLayout(), pITmpCursor->GetMark(), &tmp1);
OSL_ENSURE( pMarkTableFrame, "Table Cursor not in Content ??" );
@@ -1660,22 +1993,27 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
{
pTableFrame = nullptr;
- SwMoveFnCollection const & fnPosSect = *pPos < *pITmpCursor->GetMark()
- ? fnSectionStart
- : fnSectionEnd;
-
// then only select inside the Box
if( m_pTableCursor )
{
+ SwMoveFnCollection const & fnPosSect = *pPos < *pITmpCursor->GetMark()
+ ? fnSectionStart
+ : fnSectionEnd;
+
m_pCurrentCursor->SetMark();
*m_pCurrentCursor->GetMark() = *m_pTableCursor->GetMark();
m_pCurrentCursor->GetMkPos() = m_pTableCursor->GetMkPos();
m_pTableCursor->DeleteMark();
m_pTableCursor->SwSelPaintRects::Hide();
- }
- *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark();
- GoCurrSection( *m_pCurrentCursor, fnPosSect );
+ *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark();
+ GoCurrSection( *m_pCurrentCursor, fnPosSect );
+ }
+ else
+ {
+ eFlags &= SwCursorShell::UPDOWN;
+ *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark();
+ }
}
}
@@ -1748,8 +2086,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
m_pVisibleCursor->Show(); // show again
}
m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint
- if (Imp()->IsAccessible())
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents)
Imp()->InvalidateAccessibleCursorPosition( pTableFrame );
+#endif
return;
}
}
@@ -1772,7 +2112,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
{
SwShellCursor* pShellCursor = getShellCursor( true );
bool bChgState = true;
- const SwSectionNode* pSectNd = pShellCursor->GetNode().FindSectionNode();
+ const SwSectionNode* pSectNd = pShellCursor->GetPointNode().FindSectionNode();
if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
( !IsReadOnlyAvailable() &&
pSectNd->GetSection().IsProtectFlag() &&
@@ -1825,14 +2165,14 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
bool bPointIsStart = ( rCmp.Start() == rCmp.GetPoint() );
// move point; forward if it's the start, backwards if it's the end
- if( ! rCmp.GetPoint()->nNode.GetNode().IsContentNode() )
+ if( ! rCmp.GetPoint()->GetNode().IsContentNode() )
rCmp.Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
GoInContent );
// move mark (if exists); forward if it's the start, else backwards
if( rCmp.HasMark() )
{
- if( ! rCmp.GetMark()->nNode.GetNode().IsContentNode() )
+ if( ! rCmp.GetMark()->GetNode().IsContentNode() )
{
rCmp.Exchange();
rCmp.Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
@@ -1853,17 +2193,25 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
do {
bAgainst = false;
std::pair<Point, bool> const tmp1(pShellCursor->GetPtPos(), false);
- pFrame = pShellCursor->GetContentNode()->getLayoutFrame(GetLayout(),
+ pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame(GetLayout(),
pShellCursor->GetPoint(), &tmp1);
// if the Frame doesn't exist anymore, the complete Layout has to be
// created, because there used to be a Frame here!
if ( !pFrame )
{
+ // skip, if it is a hidden deleted cell without frame
+ if ( GetLayout()->IsHideRedlines() )
+ {
+ const SwStartNode* pNd = pShellCursor->GetPointNode().FindTableBoxStartNode();
+ if ( pNd && pNd->GetTableBox()->GetRedlineType() == RedlineType::Delete )
+ return;
+ }
+
do
{
CalcLayout();
std::pair<Point, bool> const tmp(pShellCursor->GetPtPos(), false);
- pFrame = pShellCursor->GetContentNode()->getLayoutFrame(
+ pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame(
GetLayout(), pShellCursor->GetPoint(), &tmp);
} while( !pFrame );
}
@@ -2020,8 +2368,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint
- if (Imp()->IsAccessible())
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents)
Imp()->InvalidateAccessibleCursorPosition( pFrame );
+#endif
// switch from blinking cursor to read-only-text-selection cursor
const sal_uInt64 nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
@@ -2052,76 +2402,74 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
void SwCursorShell::sendLOKCursorUpdates()
{
- SwWrtShell* pShell = GetDoc()->GetDocShell()->GetWrtShell();
- if (!pShell)
+ SwView* pView = static_cast<SwView*>(GetSfxViewShell());
+ if (!pView || !pView->GetWrtShellPtr())
return;
+ SwWrtShell* pShell = &pView->GetWrtShell();
+
SwFrame* pCurrentFrame = GetCurrFrame();
SelectionType eType = pShell->GetSelectionType();
- boost::property_tree::ptree aRootTree;
+ tools::JsonWriter aJsonWriter;
if (pCurrentFrame && (eType & SelectionType::Table) && pCurrentFrame->IsInTab())
{
const SwRect& rPageRect = pShell->GetAnyCurRect(CurRectType::Page, nullptr);
- boost::property_tree::ptree aTableColumns;
{
+ auto columnsNode = aJsonWriter.startNode("columns");
SwTabCols aTabCols;
pShell->GetTabCols(aTabCols);
const int nColumnOffset = aTabCols.GetLeftMin() + rPageRect.Left();
- aTableColumns.put("left", aTabCols.GetLeft());
- aTableColumns.put("right", aTabCols.GetRight());
- aTableColumns.put("tableOffset", nColumnOffset);
+ aJsonWriter.put("left", aTabCols.GetLeft());
+ aJsonWriter.put("right", aTabCols.GetRight());
+ aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nColumnOffset));
- boost::property_tree::ptree aEntries;
- for (size_t i = 0; i < aTabCols.Count(); ++i)
{
- auto const & rEntry = aTabCols.GetEntry(i);
- boost::property_tree::ptree aTableColumnEntry;
- aTableColumnEntry.put("position", rEntry.nPos);
- aTableColumnEntry.put("min", rEntry.nMin);
- aTableColumnEntry.put("max", rEntry.nMax);
- aTableColumnEntry.put("hidden", rEntry.bHidden);
- aEntries.push_back(std::make_pair("", aTableColumnEntry));
+ auto entriesNode = aJsonWriter.startArray("entries");
+ for (size_t i = 0; i < aTabCols.Count(); ++i)
+ {
+ auto entryNode = aJsonWriter.startStruct();
+ auto const & rEntry = aTabCols.GetEntry(i);
+ aJsonWriter.put("position", rEntry.nPos);
+ aJsonWriter.put("min", rEntry.nMin);
+ aJsonWriter.put("max", rEntry.nMax);
+ aJsonWriter.put("hidden", rEntry.bHidden);
+ }
}
- aTableColumns.push_back(std::make_pair("entries", aEntries));
}
- boost::property_tree::ptree aTableRows;
{
+ auto rowsNode = aJsonWriter.startNode("rows");
SwTabCols aTabRows;
pShell->GetTabRows(aTabRows);
const int nRowOffset = aTabRows.GetLeftMin() + rPageRect.Top();
- aTableRows.put("left", aTabRows.GetLeft());
- aTableRows.put("right", aTabRows.GetRight());
- aTableRows.put("tableOffset", nRowOffset);
+ aJsonWriter.put("left", aTabRows.GetLeft());
+ aJsonWriter.put("right", aTabRows.GetRight());
+ aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nRowOffset));
- boost::property_tree::ptree aEntries;
- for (size_t i = 0; i < aTabRows.Count(); ++i)
{
- auto const & rEntry = aTabRows.GetEntry(i);
- boost::property_tree::ptree aTableRowEntry;
- aTableRowEntry.put("position", rEntry.nPos);
- aTableRowEntry.put("min", rEntry.nMin);
- aTableRowEntry.put("max", rEntry.nMax);
- aTableRowEntry.put("hidden", rEntry.bHidden);
- aEntries.push_back(std::make_pair("", aTableRowEntry));
+ auto entriesNode = aJsonWriter.startArray("entries");
+ for (size_t i = 0; i < aTabRows.Count(); ++i)
+ {
+ auto entryNode = aJsonWriter.startStruct();
+ auto const & rEntry = aTabRows.GetEntry(i);
+ aJsonWriter.put("position", rEntry.nPos);
+ aJsonWriter.put("min", rEntry.nMin);
+ aJsonWriter.put("max", rEntry.nMax);
+ aJsonWriter.put("hidden", rEntry.bHidden);
+ }
}
- aTableRows.push_back(std::make_pair("entries", aEntries));
}
-
- aRootTree.add_child("columns", aTableColumns);
- aRootTree.add_child("rows", aTableRows);
}
- std::stringstream aStream;
- boost::property_tree::write_json(aStream, aRootTree);
- GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, aStream.str().c_str());
+ OString pChar = aJsonWriter.finishAndGetAsOString();
+ GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, pChar);
}
void SwCursorShell::RefreshBlockCursor()
@@ -2130,7 +2478,7 @@ void SwCursorShell::RefreshBlockCursor()
SwShellCursor &rBlock = m_pBlockCursor->getShellCursor();
Point aPt = rBlock.GetPtPos();
std::pair<Point, bool> const tmp(aPt, false);
- SwContentFrame* pFrame = rBlock.GetContentNode()->getLayoutFrame(
+ SwContentFrame* pFrame = rBlock.GetPointContentNode()->getLayoutFrame(
GetLayout(), rBlock.GetPoint(), &tmp);
Point aMk;
if( m_pBlockCursor->getEndPoint() && m_pBlockCursor->getStartPoint() )
@@ -2262,7 +2610,16 @@ void SwCursorShell::Push()
*/
bool SwCursorShell::Pop(PopMode const eDelete)
{
- SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
+ std::optional<SwCallLink> aLink(std::in_place, *this); // watch Cursor-Moves; call Link if needed
+ return Pop(eDelete, aLink);
+}
+
+bool SwCursorShell::Pop(PopMode const eDelete,
+ [[maybe_unused]] std::optional<SwCallLink>& roLink)
+{
+ // parameter exists only to be deleted before return
+ assert(roLink);
+ comphelper::ScopeGuard aGuard( [&]() { roLink.reset(); } );
// are there any left?
if (nullptr == m_pStackCursor)
@@ -2283,7 +2640,7 @@ bool SwCursorShell::Pop(PopMode const eDelete)
if (PopMode::DeleteCurrent == eDelete)
{
- SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ ::std::optional<SwCursorSaveState> oSaveState( *m_pCurrentCursor );
// If the visible SSelection was not changed
const Point& rPoint = pOldStack->GetPtPos();
@@ -2311,6 +2668,7 @@ bool SwCursorShell::Pop(PopMode const eDelete)
!m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::Toggle |
SwCursorSelOverFlags::ChangePos ) )
{
+ oSaveState.reset(); // prevent UAF
UpdateCursor(); // update current cursor
if (m_pTableCursor)
{ // tdf#106929 ensure m_pCurrentCursor ring is recreated from table
@@ -2337,8 +2695,8 @@ void SwCursorShell::Combine()
SwCursorSaveState aSaveState(*m_pStackCursor);
// stack cursor & current cursor in same Section?
assert(!m_pStackCursor->HasMark() ||
- CheckNodesRange(m_pStackCursor->GetMark()->nNode,
- m_pCurrentCursor->GetPoint()->nNode, true));
+ CheckNodesRange(m_pStackCursor->GetMark()->GetNode(),
+ m_pCurrentCursor->GetPoint()->GetNode(), true));
*m_pStackCursor->GetPoint() = *m_pCurrentCursor->GetPoint();
m_pStackCursor->GetPtPos() = m_pCurrentCursor->GetPtPos();
@@ -2393,13 +2751,16 @@ void SwCursorShell::ShowCursor()
if( m_bBasicHideCursor )
return;
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll());
+
m_bSVCursorVis = true;
m_pCurrentCursor->SetShowTextInputFieldOverlay( true );
+ m_pCurrentCursor->SetShowContentControlOverlay(true);
if (comphelper::LibreOfficeKit::isActive())
{
const OString aPayload = OString::boolean(m_bSVCursorVis);
- GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr());
+ GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload);
SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload);
}
@@ -2415,12 +2776,13 @@ void SwCursorShell::HideCursor()
// possibly reverse selected areas!!
CurrShell aCurr( this );
m_pCurrentCursor->SetShowTextInputFieldOverlay( false );
+ m_pCurrentCursor->SetShowContentControlOverlay(false);
m_pVisibleCursor->Hide();
if (comphelper::LibreOfficeKit::isActive())
{
OString aPayload = OString::boolean(m_bSVCursorVis);
- GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr());
+ GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload);
SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload);
}
}
@@ -2434,12 +2796,12 @@ void SwCursorShell::ShellLoseFocus()
void SwCursorShell::ShellGetFocus()
{
- comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll());
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll());
m_bHasFocus = true;
if( !m_bBasicHideCursor && VisArea().Width() )
{
- UpdateCursor( static_cast<sal_uInt16>( SwCursorShell::CHKRANGE ) );
+ UpdateCursor( o3tl::narrowing<sal_uInt16>( SwCursorShell::CHKRANGE ) );
ShowCursors( m_bSVCursorVis );
}
}
@@ -2449,7 +2811,7 @@ SwContentFrame *SwCursorShell::GetCurrFrame( const bool bCalcFrame ) const
{
CurrShell aCurr( const_cast<SwCursorShell*>(this) );
SwContentFrame *pRet = nullptr;
- SwContentNode *pNd = m_pCurrentCursor->GetContentNode();
+ SwContentNode *pNd = m_pCurrentCursor->GetPointContentNode();
if ( pNd )
{
if ( bCalcFrame )
@@ -2485,29 +2847,25 @@ void SwCursorShell::SwClientNotify(const SwModify&, const SfxHint& rHint)
m_aGrfArrivedLnk.Call(*this);
return;
}
- auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint);
- if(!pLegacy)
+ if (rHint.GetId() != SfxHintId::SwLegacyModify)
return;
+ auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
auto nWhich = pLegacy->GetWhich();
if(!nWhich)
- nWhich = sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
+ nWhich = RES_OBJECTDYING;
if( m_bCallChgLnk &&
- ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
- nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
- nWhich == RES_ATTRSET_CHG ))
+ ( !isFormatMessage(nWhich)
+ || nWhich == RES_FMT_CHG
+ || nWhich == RES_UPDATE_ATTR
+ || nWhich == RES_ATTRSET_CHG ))
// messages are not forwarded
// #i6681#: RES_UPDATE_ATTR is implicitly unset in
// SwTextNode::Insert(SwTextHint*, sal_uInt16); we react here and thus do
// not need to send the expensive RES_FMT_CHG in Insert.
CallChgLnk();
- switch(nWhich)
+ if( nWhich == RES_OBJECTDYING )
{
- case RES_OBJECTDYING:
- EndListeningAll();
- break;
- case RES_GRAPHIC_SWAPIN:
- if(m_aGrfArrivedLnk.IsSet())
- m_aGrfArrivedLnk.Call(*this);
+ EndListeningAll();
}
}
@@ -2546,14 +2904,14 @@ OUString SwCursorShell::GetSelText() const
if (GetLayout()->HasMergedParas())
{
SwContentFrame const*const pFrame(GetCurrFrame(false));
- if (FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->nNode.GetIndex()))
+ if (pFrame && FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->GetNodeIndex()))
{
OUStringBuffer buf;
SwPosition const*const pStart(m_pCurrentCursor->Start());
SwPosition const*const pEnd(m_pCurrentCursor->End());
- for (sal_uLong i = pStart->nNode.GetIndex(); i <= pEnd->nNode.GetIndex(); ++i)
+ for (SwNodeOffset i = pStart->GetNodeIndex(); i <= pEnd->GetNodeIndex(); ++i)
{
- SwNode const& rNode(*pStart->nNode.GetNodes()[i]);
+ SwNode const& rNode(*pStart->GetNodes()[i]);
assert(!rNode.IsEndNode());
if (rNode.IsStartNode())
{
@@ -2561,11 +2919,11 @@ OUString SwCursorShell::GetSelText() const
}
else if (rNode.IsTextNode())
{
- sal_Int32 const nStart(i == pStart->nNode.GetIndex()
- ? pStart->nContent.GetIndex()
+ sal_Int32 const nStart(i == pStart->GetNodeIndex()
+ ? pStart->GetContentIndex()
: 0);
- sal_Int32 const nEnd(i == pEnd->nNode.GetIndex()
- ? pEnd->nContent.GetIndex()
+ sal_Int32 const nEnd(i == pEnd->GetNodeIndex()
+ ? pEnd->GetContentIndex()
: rNode.GetTextNode()->Len());
buf.append(rNode.GetTextNode()->GetExpandText(
GetLayout(),
@@ -2577,21 +2935,22 @@ OUString SwCursorShell::GetSelText() const
aText = buf.makeStringAndClear();
}
}
- else if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() ==
- m_pCurrentCursor->GetMark()->nNode.GetIndex() )
+ else if( m_pCurrentCursor->GetPoint()->GetNodeIndex() ==
+ m_pCurrentCursor->GetMark()->GetNodeIndex() )
{
- SwTextNode* pTextNd = m_pCurrentCursor->GetNode().GetTextNode();
+ SwTextNode* pTextNd = m_pCurrentCursor->GetPointNode().GetTextNode();
if( pTextNd )
{
- const sal_Int32 nStt = m_pCurrentCursor->Start()->nContent.GetIndex();
+ const sal_Int32 nStt = m_pCurrentCursor->Start()->GetContentIndex();
aText = pTextNd->GetExpandText(GetLayout(), nStt,
- m_pCurrentCursor->End()->nContent.GetIndex() - nStt );
+ m_pCurrentCursor->End()->GetContentIndex() - nStt );
}
}
return aText;
}
/** get the nth character of the current SSelection
+ in the same paragraph as the start/end.
@param bEnd Start counting from the end? From start otherwise.
@param nOffset position of the character
@@ -2603,12 +2962,18 @@ sal_Unicode SwCursorShell::GetChar( bool bEnd, tools::Long nOffset )
const SwPosition* pPos = !m_pCurrentCursor->HasMark() ? m_pCurrentCursor->GetPoint()
: bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start();
- SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode();
+ SwTextNode* pTextNd = pPos->GetNode().GetTextNode();
if( !pTextNd )
return 0;
- const sal_Int32 nPos = pPos->nContent.GetIndex();
- const OUString& rStr = pTextNd->GetText();
+ SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTextNd->getLayoutFrame(GetLayout())));
+ if (!pFrame)
+ {
+ return 0;
+ }
+
+ const sal_Int32 nPos(sal_Int32(pFrame->MapModelToViewPos(*pPos)));
+ const OUString& rStr(pFrame->GetText());
sal_Unicode cCh = 0;
if (((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.getLength())
@@ -2628,10 +2993,10 @@ bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 nCount )
return false; // no selection
SwPosition* pPos = bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start();
- SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode();
+ SwTextNode* pTextNd = pPos->GetNode().GetTextNode();
assert(pTextNd);
- sal_Int32 nPos = pPos->nContent.GetIndex();
+ sal_Int32 nPos = pPos->GetContentIndex();
if( bEnd )
{
if ((nPos + nCount) <= pTextNd->GetText().getLength())
@@ -2646,7 +3011,7 @@ bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 nCount )
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
- pPos->nContent = nPos;
+ pPos->SetContent(nPos) ;
UpdateCursor();
return true;
@@ -2671,7 +3036,7 @@ bool SwCursorShell::SetVisibleCursor( const Point &rPt )
SetInFrontOfLabel( false ); // #i27615#
// show only in TextNodes
- SwTextNode* pTextNd = aPos.nNode.GetNode().GetTextNode();
+ SwTextNode* pTextNd = aPos.GetNode().GetTextNode();
if( !pTextNd )
return false;
@@ -2726,7 +3091,7 @@ bool SwCursorShell::IsOverReadOnlyPos( const Point& rPt ) const
SwPaM aPam( *m_pCurrentCursor->GetPoint() );
GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt );
// form view
- return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
+ return aPam.HasReadonlySel(GetViewOptions()->IsFormView(), false);
}
/** Get the number of elements in the ring of cursors
@@ -2750,14 +3115,14 @@ sal_uInt16 SwCursorShell::GetCursorCnt( bool bAll ) const
bool SwCursorShell::IsStartOfDoc() const
{
- if( m_pCurrentCursor->GetPoint()->nContent.GetIndex() )
+ if( m_pCurrentCursor->GetPoint()->GetContentIndex() )
return false;
// after EndOfIcons comes the content selection (EndNd+StNd+ContentNd)
SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
if( !aIdx.GetNode().IsContentNode() )
- GetDoc()->GetNodes().GoNext( &aIdx );
- return aIdx == m_pCurrentCursor->GetPoint()->nNode;
+ SwNodes::GoNext(&aIdx);
+ return aIdx == m_pCurrentCursor->GetPoint()->GetNode();
}
bool SwCursorShell::IsEndOfDoc() const
@@ -2767,8 +3132,8 @@ bool SwCursorShell::IsEndOfDoc() const
if( !pCNd )
pCNd = SwNodes::GoPrevious( &aIdx );
- return aIdx == m_pCurrentCursor->GetPoint()->nNode &&
- pCNd->Len() == m_pCurrentCursor->GetPoint()->nContent.GetIndex();
+ return aIdx == m_pCurrentCursor->GetPoint()->GetNode() && pCNd &&
+ pCNd->Len() == m_pCurrentCursor->GetPoint()->GetContentIndex();
}
/** Invalidate cursors
@@ -2797,8 +3162,7 @@ bool SwCursorShell::ParkTableCursor()
void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing )
{
- const SwPosition *pStt = pDelRg->Start(),
- *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
+ auto [pStt, pEnd] = pDelRg->StartEnd(); // SwPosition*
SwPaM *pTmpDel = nullptr, *pTmp = *ppDelRing;
@@ -2809,9 +3173,7 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing )
if (!pTmp)
break;
- const SwPosition *pTmpStt = pTmp->Start(),
- *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
- pTmp->GetMark() : pTmp->GetPoint();
+ auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition*
// If a SPoint or GetMark are in a cursor area then cancel the old area.
// During comparison keep in mind that End() is outside the area.
if( *pStt <= *pTmpStt )
@@ -2851,8 +3213,7 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing )
}
else
{
- pTmpDel->GetPoint()->nContent.Assign(nullptr, 0);
- pTmpDel->GetPoint()->nNode = 0;
+ pTmpDel->GetPoint()->Assign(SwNodeOffset(0));
pTmpDel->DeleteMark();
}
pTmpDel = nullptr;
@@ -2870,12 +3231,12 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing )
@param rIdx ???
*/
-void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx )
+void SwCursorShell::ParkCursor( const SwNode &rIdx )
{
- SwNode *pNode = &rIdx.GetNode();
+ const SwNode *pNode = &rIdx;
// create a new PaM
- std::unique_ptr<SwPaM> pNew( new SwPaM( *GetCursor()->GetPoint() ) );
+ SwPaM aNew( *GetCursor()->GetPoint() );
if( pNode->GetStartNode() )
{
pNode = pNode->StartOfSectionNode();
@@ -2883,18 +3244,18 @@ void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx )
{
// the given node is in a table, thus park cursor to table node
// (outside of the table)
- pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() );
}
else
// Also on the start node itself. Then we need to request the start
// node always via its end node! (StartOfSelection of StartNode is
// the parent)
- pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
+ aNew.GetPoint()->Assign( *pNode->EndOfSectionNode()->StartOfSectionNode() );
}
else
- pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
- pNew->SetMark();
- pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
+ aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() );
+ aNew.SetMark();
+ aNew.GetPoint()->Assign(*pNode->EndOfSectionNode());
// take care of all shells
for(SwViewShell& rTmp : GetRingContainer())
@@ -2902,21 +3263,20 @@ void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx )
if( auto pSh = dynamic_cast<SwCursorShell *>(&rTmp))
{
if (pSh->m_pStackCursor)
- pSh->ParkPams(pNew.get(), &pSh->m_pStackCursor);
+ pSh->ParkPams(&aNew, &pSh->m_pStackCursor);
- pSh->ParkPams( pNew.get(), &pSh->m_pCurrentCursor );
+ pSh->ParkPams( &aNew, &pSh->m_pCurrentCursor );
if( pSh->m_pTableCursor )
{
// set table cursor always to 0 and the current one always to
// the beginning of the table
SwPaM* pTCursor = pSh->GetTableCrs();
- SwNode* pTableNd = pTCursor->GetPoint()->nNode.GetNode().FindTableNode();
+ SwNode* pTableNd = pTCursor->GetPoint()->GetNode().FindTableNode();
if ( pTableNd )
{
- pTCursor->GetPoint()->nContent.Assign(nullptr, 0);
- pTCursor->GetPoint()->nNode = 0;
+ pTCursor->GetPoint()->Assign(SwNodeOffset(0));
pTCursor->DeleteMark();
- pSh->m_pCurrentCursor->GetPoint()->nNode = *pTableNd;
+ pSh->m_pCurrentCursor->GetPoint()->Assign( *pTableNd );
}
}
}
@@ -2944,18 +3304,18 @@ SwCursorShell::SwCursorShell( SwCursorShell& rShell, vcl::Window *pInitWin )
, m_nCursorMove( 0 )
, m_eMvState( CursorMoveState::NONE )
, m_eEnhancedTableSel(SwTable::SEARCH_NONE)
- , m_sMarkedListId()
, m_nMarkedListLevel( 0 )
, m_oldColFrame(nullptr)
{
CurrShell aCurr( this );
// only keep the position of the current cursor of the copy shell
m_pCurrentCursor = new SwShellCursor( *this, *(rShell.m_pCurrentCursor->GetPoint()) );
- m_pCurrentCursor->GetContentNode()->Add( this );
+ m_pCurrentCursor->GetPointContentNode()->Add( this );
m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd =
m_bGCAttr = m_bIgnoreReadonly = m_bSelTableCells = m_bBasicHideCursor =
m_bOverwriteCursor = false;
+ m_bSendAccessibleCursorEvents = true;
m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true;
m_bSVCursorVis = true;
m_bSetCursorInReadOnly = true;
@@ -2981,7 +3341,6 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin,
, m_nCursorMove( 0 )
, m_eMvState( CursorMoveState::NONE ) // state for crsr-travelling - GetModelPositionForViewPoint
, m_eEnhancedTableSel(SwTable::SEARCH_NONE)
- , m_sMarkedListId()
, m_nMarkedListLevel( 0 )
, m_oldColFrame(nullptr)
{
@@ -2990,9 +3349,9 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin,
SwNodes& rNds = rDoc.GetNodes();
SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
- SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to the first ContentNode
+ SwContentNode* pCNd = SwNodes::GoNext(&aNodeIdx); // go to the first ContentNode
- m_pCurrentCursor = new SwShellCursor( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
+ m_pCurrentCursor = new SwShellCursor( *this, SwPosition( aNodeIdx, pCNd, 0 ) );
// Register shell as dependent at current node. As a result all attribute
// changes can be forwarded via the Link.
@@ -3001,6 +3360,7 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin,
m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd =
m_bGCAttr = m_bIgnoreReadonly = m_bSelTableCells = m_bBasicHideCursor =
m_bOverwriteCursor = false;
+ m_bSendAccessibleCursorEvents = true;
m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true;
m_bSVCursorVis = true;
m_bSetCursorInReadOnly = true;
@@ -3061,8 +3421,8 @@ bool SwCursorShell::ShouldWait() const
return true;
SwPaM* pPam = GetCursor();
- return pPam->Start()->nNode.GetIndex() + 10 <
- pPam->End()->nNode.GetIndex();
+ return pPam->Start()->GetNodeIndex() + SwNodeOffset(10) <
+ pPam->End()->GetNodeIndex();
}
size_t SwCursorShell::UpdateTableSelBoxes()
@@ -3124,14 +3484,14 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
GetDoc()->GetDocShell()->IsReadOnlyUI() )
return true;
- if( m_pCurrentCursor->HasMark() )
+ if( m_pCurrentCursor->HasMark() && !mbSelectAll )
ClearMark();
// first check for frames
- SwNodeIndex& rNdIdx = m_pCurrentCursor->GetPoint()->nNode;
- sal_uLong nNdIdx = rNdIdx.GetIndex(); // keep backup
+ SwPosition& rNdPos = *m_pCurrentCursor->GetPoint();
+ SwNodeOffset nNdIdx = rNdPos.GetNodeIndex(); // keep backup
SwNodes& rNds = mxDoc->GetNodes();
- SwContentNode* pCNd = rNdIdx.GetNode().GetContentNode();
+ SwContentNode* pCNd = rNdPos.GetNode().GetContentNode();
const SwContentFrame * pFrame;
if (pCNd && nullptr != (pFrame = pCNd->getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint())) &&
@@ -3141,19 +3501,19 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
// skip protected frame
SwPaM aPam( *m_pCurrentCursor->GetPoint() );
aPam.SetMark();
- aPam.GetMark()->nNode = rNds.GetEndOfContent();
- aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
+ aPam.GetMark()->Assign( rNds.GetEndOfContent() );
+ aPam.GetPoint()->Assign( *pCNd->EndOfSectionNode() );
bool bFirst = false;
if( nullptr == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward )))
{
- aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
+ aPam.GetMark()->Assign( *rNds.GetEndOfPostIts().StartOfSectionNode() );
pCNd = ::GetNode( aPam, bFirst, fnMoveBackward );
}
if( !pCNd ) // should *never* happen
{
- rNdIdx = nNdIdx; // back to old node
+ rNdPos.Assign(nNdIdx); // back to old node
return false;
}
*m_pCurrentCursor->GetPoint() = *aPam.GetPoint();
@@ -3161,48 +3521,47 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
else if( bOnlyText && pCNd && pCNd->IsNoTextNode() )
{
// set to beginning of document
- rNdIdx = mxDoc->GetNodes().GetEndOfExtras();
- m_pCurrentCursor->GetPoint()->nContent.Assign( mxDoc->GetNodes().GoNext(
- &rNdIdx ), 0 );
- nNdIdx = rNdIdx.GetIndex();
+ rNdPos.Assign( mxDoc->GetNodes().GetEndOfExtras() );
+ SwNodes::GoNext(&rNdPos);
+ nNdIdx = rNdPos.GetNodeIndex();
}
bool bOk = true;
// #i9059# cursor may not stand in protected cells
// (unless cursor in protected areas is OK.)
- const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
+ const SwTableNode* pTableNode = rNdPos.GetNode().FindTableNode();
if( !IsReadOnlyAvailable() &&
- pTableNode != nullptr && rNdIdx.GetNode().IsProtect() )
+ pTableNode != nullptr && rNdPos.GetNode().IsProtect() )
{
// we're in a table, and we're in a protected area, so we're
// probably in a protected cell.
// move forward into non-protected area.
- SwPaM aPam( rNdIdx.GetNode(), 0 );
- while( aPam.GetNode().IsProtect() &&
+ SwPaM aPam( rNdPos.GetNode(), 0 );
+ while( aPam.GetPointNode().IsProtect() &&
aPam.Move( fnMoveForward, GoInContent ) )
; // nothing to do in the loop; the aPam.Move does the moving!
// didn't work? then go backwards!
- if( aPam.GetNode().IsProtect() )
+ if( aPam.GetPointNode().IsProtect() )
{
- SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
+ SwPaM aTmpPaM( rNdPos.GetNode(), 0 );
aPam = aTmpPaM;
- while( aPam.GetNode().IsProtect() &&
+ while( aPam.GetPointNode().IsProtect() &&
aPam.Move( fnMoveBackward, GoInContent ) )
; // nothing to do in the loop; the aPam.Move does the moving!
}
// if we're successful, set the new position
- if( ! aPam.GetNode().IsProtect() )
+ if( ! aPam.GetPointNode().IsProtect() )
{
*m_pCurrentCursor->GetPoint() = *aPam.GetPoint();
}
}
// in a protected frame
- const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
+ const SwSectionNode* pSectNd = rNdPos.GetNode().FindSectionNode();
if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
( !IsReadOnlyAvailable() &&
pSectNd->GetSection().IsProtectFlag() )) )
@@ -3217,10 +3576,10 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
for (;;)
{
if (bGoNextSection)
- pCNd = rNds.GoNextSection( &rNdIdx,
+ pCNd = SwNodes::GoNextSection( &rNdPos,
true, !IsReadOnlyAvailable() );
else
- pCNd = SwNodes::GoPrevSection( &rNdIdx,
+ pCNd = SwNodes::GoPrevSection( &rNdPos,
true, !IsReadOnlyAvailable() );
if ( pCNd == nullptr) break;
// moved inside a table -> check if it is protected
@@ -3249,7 +3608,7 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
}
}
- if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
+ if( bOk && rNdPos.GetNodeIndex() < rNds.GetEndOfExtras().GetIndex() )
{
// also check for Fly - might be protected as well
pFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr);
@@ -3268,19 +3627,19 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText )
{
if( !nLoopCnt )
bGoNextSection = false;
- rNdIdx = nNdIdx;
+ rNdPos.Assign( nNdIdx );
}
}
}
if( bOk )
{
- pCNd = rNdIdx.GetNode().GetContentNode();
- const sal_Int32 nContent = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
- m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, nContent );
+ pCNd = rNdPos.GetNode().GetContentNode();
+ const sal_Int32 nContent = rNdPos.GetNodeIndex() < nNdIdx ? pCNd->Len() : 0;
+ m_pCurrentCursor->GetPoint()->SetContent( nContent );
}
else
{
- pCNd = rNdIdx.GetNode().GetContentNode();
+ pCNd = rNdPos.GetNode().GetContentNode();
// if cursor in hidden frame, always move it
if (!pCNd || !pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr))
{
@@ -3346,8 +3705,16 @@ void SwCursorShell::SetReadOnlyAvailable( bool bFlag )
}
}
-bool SwCursorShell::HasReadonlySel() const
+bool SwCursorShell::HasReadonlySel(bool const isReplace) const
{
+ // Treat selections that span over start or end of paragraph of an outline node
+ // with folded outline content as read-only.
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell();
+ if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected())
+ return true;
+ }
bool bRet = false;
// If protected area is to be ignored, then selections are never read-only.
if ((IsReadOnlyAvailable() || GetViewOptions()->IsFormView() ||
@@ -3356,14 +3723,15 @@ bool SwCursorShell::HasReadonlySel() const
{
if ( m_pTableCursor != nullptr )
{
+ // TODO: handling when a table cell (cells) is selected
bRet = m_pTableCursor->HasReadOnlyBoxSel()
- || m_pTableCursor->HasReadonlySel( GetViewOptions()->IsFormView() );
+ || m_pTableCursor->HasReadonlySel(GetViewOptions()->IsFormView(), isReplace);
}
else
{
for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer())
{
- if( rCursor.HasReadonlySel( GetViewOptions()->IsFormView() ) )
+ if (rCursor.HasReadonlySel(GetViewOptions()->IsFormView(), isReplace))
{
bRet = true;
break;
@@ -3374,22 +3742,50 @@ bool SwCursorShell::HasReadonlySel() const
return bRet;
}
-bool SwCursorShell::IsSelFullPara() const
+bool SwCursorShell::HasHiddenSections() const
{
+ // Treat selections that span over start or end of paragraph of an outline node
+ // with folded outline content as read-only.
+ if (GetViewOptions()->IsShowOutlineContentVisibilityButton())
+ {
+ SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell();
+ if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected())
+ return true;
+ }
bool bRet = false;
- if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() ==
- m_pCurrentCursor->GetMark()->nNode.GetIndex() && !m_pCurrentCursor->IsMultiSelection() )
+ if ( m_pTableCursor != nullptr )
{
- sal_Int32 nStt = m_pCurrentCursor->GetPoint()->nContent.GetIndex();
- sal_Int32 nEnd = m_pCurrentCursor->GetMark()->nContent.GetIndex();
- if( nStt > nEnd )
+ bRet = m_pTableCursor->HasHiddenBoxSel()
+ || m_pTableCursor->HasHiddenSections();
+ }
+ else
+ {
+ for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer())
{
- sal_Int32 nTmp = nStt;
- nStt = nEnd;
- nEnd = nTmp;
+ if (rCursor.HasHiddenSections())
+ {
+ bRet = true;
+ break;
+ }
}
- const SwContentNode* pCNd = m_pCurrentCursor->GetContentNode();
+ }
+
+ return bRet;
+}
+
+bool SwCursorShell::IsSelFullPara() const
+{
+ bool bRet = false;
+
+ if( m_pCurrentCursor->GetPoint()->GetNodeIndex() ==
+ m_pCurrentCursor->GetMark()->GetNodeIndex() && !m_pCurrentCursor->IsMultiSelection() )
+ {
+ sal_Int32 nStt = m_pCurrentCursor->GetPoint()->GetContentIndex();
+ sal_Int32 nEnd = m_pCurrentCursor->GetMark()->GetContentIndex();
+ if( nStt > nEnd )
+ std::swap( nStt, nEnd );
+ const SwContentNode* pCNd = m_pCurrentCursor->GetPointContentNode();
bRet = pCNd && !nStt && nEnd == pCNd->Len();
}
return bRet;
@@ -3425,18 +3821,18 @@ bool SwCursorShell::IsInRightToLeftText() const
return SvxFrameDirection::Vertical_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir;
}
-/// If the current cursor position is inside a hidden range, the hidden range
-/// is selected.
-bool SwCursorShell::SelectHiddenRange()
+/// If the current cursor position is inside a hidden range true is returned. If bSelect is
+/// true, the hidden range is selected. If bSelect is false, the hidden range is not selected.
+bool SwCursorShell::IsInHiddenRange(const bool bSelect)
{
bool bRet = false;
if ( !GetViewOptions()->IsShowHiddenChar() && !m_pCurrentCursor->HasMark() )
{
SwPosition& rPt = *m_pCurrentCursor->GetPoint();
- const SwTextNode* pNode = rPt.nNode.GetNode().GetTextNode();
+ const SwTextNode* pNode = rPt.GetNode().GetTextNode();
if ( pNode )
{
- const sal_Int32 nPos = rPt.nContent.GetIndex();
+ const sal_Int32 nPos = rPt.GetContentIndex();
// check if nPos is in hidden range
sal_Int32 nHiddenStart;
@@ -3444,9 +3840,12 @@ bool SwCursorShell::SelectHiddenRange()
SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
if ( COMPLETE_STRING != nHiddenStart )
{
- // make selection:
- m_pCurrentCursor->SetMark();
- m_pCurrentCursor->GetMark()->nContent = nHiddenEnd;
+ if (bSelect)
+ {
+ // make selection:
+ m_pCurrentCursor->SetMark();
+ m_pCurrentCursor->GetMark()->SetContent(nHiddenEnd);
+ }
bRet = true;
}
}
@@ -3455,7 +3854,7 @@ bool SwCursorShell::SelectHiddenRange()
return bRet;
}
-sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
+sal_Int32 SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
bool bSearchInNotes,
SwDocPositions eStart, SwDocPositions eEnd,
bool& bCancel,
@@ -3467,14 +3866,14 @@ sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
delete m_pTableCursor;
m_pTableCursor = nullptr;
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
- sal_uLong nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd,
+ sal_Int32 nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd,
bCancel, eRng, bReplace, GetLayout());
if( nRet || bCancel )
UpdateCursor();
return nRet;
}
-sal_uLong SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl,
+sal_Int32 SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl,
SwDocPositions eStart, SwDocPositions eEnd,
bool& bCancel,
FindRanges eRng,
@@ -3485,14 +3884,14 @@ sal_uLong SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl,
delete m_pTableCursor;
m_pTableCursor = nullptr;
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
- sal_uLong nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng,
+ sal_Int32 nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng,
pReplFormat );
if( nRet )
UpdateCursor();
return nRet;
}
-sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet,
+sal_Int32 SwCursorShell::FindAttrs( const SfxItemSet& rSet,
bool bNoCollections,
SwDocPositions eStart, SwDocPositions eEnd,
bool& bCancel,
@@ -3505,7 +3904,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet,
delete m_pTableCursor;
m_pTableCursor = nullptr;
SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
- sal_uLong nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd,
+ sal_Int32 nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd,
bCancel, eRng, pSearchOpt, rReplSet, GetLayout());
if( nRet )
UpdateCursor();
@@ -3515,7 +3914,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet,
void SwCursorShell::SetSelection( const SwPaM& rCursor )
{
StartAction();
- SwPaM* pCursor = GetCursor();
+ SwCursor* pCursor = GetCursor();
*pCursor->GetPoint() = *rCursor.GetPoint();
if(rCursor.GetNext() != &rCursor)
{
@@ -3558,10 +3957,10 @@ static const SwStartNode* lcl_NodeContext( const SwNode& rNode )
@param aPos the position to check.
*/
-bool sw_PosOk(const SwPosition & aPos)
+static bool sw_PosOk(const SwPosition & aPos)
{
- return nullptr != aPos.nNode.GetNode().GetContentNode() &&
- aPos.nContent.GetIdxReg();
+ return nullptr != aPos.GetNode().GetContentNode() &&
+ aPos.GetContentNode();
}
/**
@@ -3603,21 +4002,35 @@ void SwCursorShell::ClearUpCursors()
pStartCursor->DeleteMark();
bChanged = true;
}
+ if (pStartCursor->GetPoint()->GetNode().IsTableNode())
+ {
+ // tdf#106959: When cursor points to start of a table, the proper content
+ // node is the first one inside the table, not the previous one
+ SwNodeIndex aIdx(pStartCursor->GetPoint()->GetNode());
+ if (SwNode* pNode = SwNodes::GoNext(&aIdx))
+ {
+ SwPaM aTmpPam(*pNode);
+ *pStartCursor = aTmpPam;
+ bChanged = true;
+ }
+ }
if( !sw_PosOk( *pStartCursor->GetPoint() ) )
{
SwNodes & aNodes = GetDoc()->GetNodes();
- const SwNode* pStart = lcl_NodeContext( pStartCursor->GetPoint()->nNode.GetNode() );
- SwNodeIndex aIdx( pStartCursor->GetPoint()->nNode );
+ const SwNode* pStart = lcl_NodeContext( pStartCursor->GetPoint()->GetNode() );
+ SwNodeIndex aIdx( pStartCursor->GetPoint()->GetNode() );
SwNode * pNode = SwNodes::GoPrevious(&aIdx);
if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart )
- aNodes.GoNext( &aIdx );
- if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart )
{
- // If the start entry of the ring is invalid replace it with a
- // cursor pointing to the beginning of the first content node in the
- // document.
- aIdx = *(aNodes.GetEndOfContent().StartOfSectionNode());
- pNode = aNodes.GoNext( &aIdx );
+ pNode = SwNodes::GoNext(&aIdx);
+ if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart )
+ {
+ // If the start entry of the ring is invalid replace it with a
+ // cursor pointing to the beginning of the first content node in the
+ // document.
+ aIdx = *(aNodes.GetEndOfContent().StartOfSectionNode());
+ pNode = SwNodes::GoNext(&aIdx);
+ }
}
bool bFound = (pNode != nullptr);
@@ -3652,16 +4065,16 @@ OUString SwCursorShell::GetCursorDescr() const
void SwCursorShell::dumpAsXml(xmlTextWriterPtr pWriter) const
{
- xmlTextWriterStartElement(pWriter, BAD_CAST("SwCursorShell"));
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwCursorShell"));
SwViewShell::dumpAsXml(pWriter);
- xmlTextWriterStartElement(pWriter, BAD_CAST("m_pCurrentCursor"));
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_pCurrentCursor"));
for (const SwPaM& rPaM : m_pCurrentCursor->GetRingContainer())
rPaM.dumpAsXml(pWriter);
- xmlTextWriterEndElement(pWriter);
+ (void)xmlTextWriterEndElement(pWriter);
- xmlTextWriterEndElement(pWriter);
+ (void)xmlTextWriterEndElement(pWriter);
}
static void lcl_FillRecognizerData( std::vector< OUString >& rSmartTagTypes,
@@ -3682,6 +4095,7 @@ static void lcl_FillRecognizerData( std::vector< OUString >& rSmartTagTypes,
if ( pArea )
{
rSmartTagTypes.push_back( pArea->maType );
+ aStringKeyMaps.push_back( pArea->mxPropertyBag );
}
}
}
@@ -3696,14 +4110,11 @@ static void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
SwTextNode& rNode, sal_Int32 nBegin, sal_Int32 nLen )
{
// create SwPosition for nStartIndex
- SwIndex aIndex( &rNode, nBegin );
- SwPosition aStartPos( rNode, aIndex );
-
+ SwPosition aStartPos( rNode, nBegin );
// create SwPosition for nEndIndex
- SwPosition aEndPos( aStartPos );
- aEndPos.nContent = nBegin + nLen;
+ SwPosition aEndPos( rNode, nBegin + nLen );
- const uno::Reference<text::XTextRange> xRange =
+ const rtl::Reference<SwXTextRange> xRange =
SwXTextRange::CreateXTextRange(rNode.GetDoc(), aStartPos, &aEndPos);
rRange = xRange;
@@ -3717,8 +4128,8 @@ void SwCursorShell::GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes,
return;
SwPaM* pCursor = GetCursor();
- SwPosition aPos( *pCursor->GetPoint() );
- SwTextNode *pNode = aPos.nNode.GetNode().GetTextNode();
+ SwPosition aPos(*pCursor->Start());
+ SwTextNode *pNode = aPos.GetNode().GetTextNode();
if ( !pNode || pNode->IsInProtectSect() )
return;
@@ -3726,7 +4137,7 @@ void SwCursorShell::GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes,
if ( !pSmartTagList )
return;
- sal_Int32 nCurrent = aPos.nContent.GetIndex();
+ sal_Int32 nCurrent = aPos.GetContentIndex();
sal_Int32 nBegin = nCurrent;
sal_Int32 nLen = 1;
@@ -3752,6 +4163,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
SwPosition aPos( *pCursor->GetPoint() );
Point aPt( rPt );
SwCursorMoveState eTmpState( CursorMoveState::SetOnlyText );
+ eTmpState.m_bPosMatchesBounds = true; // treat last half of character same as first half
SwSpecialPos aSpecialPos;
eTmpState.m_pSpecialPos = &aSpecialPos;
SwTextNode *pNode;
@@ -3759,7 +4171,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
if( !GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &eTmpState ) )
return;
- pNode = aPos.nNode.GetNode().GetTextNode();
+ pNode = aPos.GetNode().GetTextNode();
if( !pNode )
return;
pSmartTagList = pNode->GetSmartTags();
@@ -3768,7 +4180,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
if( pNode->IsInProtectSect() )
return;
- sal_Int32 nBegin = aPos.nContent.GetIndex();
+ sal_Int32 nBegin = aPos.GetContentIndex();
sal_Int32 nLen = 1;
if (!pSmartTagList->InWrongWord(nBegin, nLen) || pNode->IsSymbolAt(nBegin))
@@ -3780,9 +4192,9 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
//save the start and end positions of the line and the starting point
Push();
LeftMargin();
- const sal_Int32 nLineStart = GetCursor()->GetPoint()->nContent.GetIndex();
+ const sal_Int32 nLineStart = GetCursor()->GetPoint()->GetContentIndex();
RightMargin();
- const sal_Int32 nLineEnd = GetCursor()->GetPoint()->nContent.GetIndex();
+ const sal_Int32 nLineEnd = GetCursor()->GetPoint()->GetContentIndex();
Pop(PopMode::DeleteCurrent);
// make sure the selection build later from the data below does not
@@ -3798,7 +4210,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
while (pChar && *pChar-- == CH_TXTATR_INWORD)
++nRight;
- aPos.nContent = nBegin + nLeft;
+ aPos.SetContent( nBegin + nLeft );
pCursor = GetCursor();
*pCursor->GetPoint() = aPos;
pCursor->SetMark();
@@ -3810,18 +4222,18 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
const sal_Int32 nWordEnd = std::min(nBegin + nLen - nLeft - nRight, nLineEnd);
Push();
pCursor->DeleteMark();
- SwIndex& rContent = GetCursor()->GetPoint()->nContent;
- rContent = nWordStart;
+ SwPosition& rPos = *GetCursor()->GetPoint();
+ rPos.SetContent( nWordStart );
SwRect aStartRect;
SwCursorMoveState aState;
aState.m_bRealWidth = true;
- SwContentNode* pContentNode = pCursor->GetContentNode();
+ SwContentNode* pContentNode = pCursor->GetPointContentNode();
std::pair<Point, bool> const tmp(rPt, false);
SwContentFrame *pContentFrame = pContentNode->getLayoutFrame(
GetLayout(), pCursor->GetPoint(), &tmp);
pContentFrame->GetCharRect( aStartRect, *pCursor->GetPoint(), &aState );
- rContent = nWordEnd - 1;
+ rPos.SetContent( nWordEnd - 1 );
SwRect aEndRect;
pContentFrame->GetCharRect( aEndRect, *pCursor->GetPoint(),&aState );
rSelectRect = aStartRect.Union( aEndRect );