/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// CreateNewSavePos is virtual so that derived classes of cursor can implement // own SaveObjects if needed and validate them in the virtual check routines. void SwCursor::SaveState()
{
m_vSavePos.emplace_back( *this );
}
/// determine if point is outside of the node-array's content area bool SwCursor::IsNoContent() const
{ return GetPoint()->GetNodeIndex() <
GetDoc().GetNodes().GetEndOfExtras().GetIndex();
}
// is there a protected section in the section? if( HasMark() && bSkipOverProtectSections)
{
SwNodeOffset nSttIdx = GetMark()->GetNodeIndex(),
nEndIdx = GetPoint()->GetNodeIndex(); if( nEndIdx <= nSttIdx )
std::swap( nSttIdx, nEndIdx );
const SwSectionFormats& rFormats = rDoc.GetSections(); for( SwSectionFormats::size_type n = 0; n < rFormats.size(); ++n )
{ const SwSectionFormat* pFormat = rFormats[n]; const SvxProtectItem& rProtect = pFormat->GetProtect(); if( rProtect.IsContentProtected() )
{ const SwFormatContent& rContent = pFormat->GetContent(false);
OSL_ENSURE( rContent.GetContentIdx(), "No SectionNode?" );
SwNodeOffset nIdx = rContent.GetContentIdx()->GetIndex(); if( nSttIdx <= nIdx && nEndIdx >= nIdx )
{ // if it is no linked section then we cannot select it const SwSection& rSect = *pFormat->GetSection(); if( SectionType::Content == rSect.GetType() )
{
RestoreSavePos(); returntrue;
}
}
}
}
}
}
const SwNode* pNd = &GetPoint()->GetNode(); if( pNd->IsContentNode() && !dynamic_cast<SwUnoCursor*>(this) )
{ const SwContentFrame* pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ); if ( (SwCursorSelOverFlags::ChangePos & eFlags) //allowed to change position if it's a bad one
&& pFrame && pFrame->isFrameAreaDefinitionValid()
&& !pFrame->getFrameArea().Height() //a bad zero height position
&& !InputFieldAtPos(GetPoint()) ) //unless it's a (vertical) input field
{ // skip to the next/prev valid paragraph with a layout
SwPosition& rPtPos = *GetPoint(); bool bGoNxt = m_vSavePos.back().nNode < rPtPos.GetNodeIndex(); for (;;)
{
pFrame = bGoNxt ? pFrame->FindNextCnt(true) : pFrame->FindPrevCnt(); if (!pFrame || 0 != pFrame->getFrameArea().Height() ) break;
}
// #i72394# skip to prev/next valid paragraph with a layout in case // the first search did not succeed: if( !pFrame )
{
bGoNxt = !bGoNxt;
pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ); while ( pFrame && 0 == pFrame->getFrameArea().Height() )
{
pFrame = bGoNxt ? pFrame->FindNextCnt(true) : pFrame->FindPrevCnt();
}
}
// set this ContentNode as new position
rPtPos.Assign( *pCNd ); // assign corresponding ContentIndex const sal_Int32 nTmpPos = bGoNxt ? 0 : pCNd->Len();
GetPoint()->SetContent( nTmpPos );
}
if (rPtPos.GetNodeIndex() == m_vSavePos.back().nNode
&& GetPoint()->GetContentIndex() == m_vSavePos.back().nContent)
{ // new position equals saved one // --> trigger restore of saved pos by setting <pFrame> to NULL - see below
pFrame = nullptr;
}
if ( IsInProtectTable( true ) )
{ // new position in protected table // --> trigger restore of saved pos by setting <pFrame> to NULL - see below
pFrame = nullptr;
}
}
}
if( !pFrame )
{
assert(!m_vSavePos.empty());
SwContentNode const*const pSaveNode(rNds[m_vSavePos.back().nNode]->GetContentNode()); // if the old position already didn't have a frame, allow moving // anyway, hope the caller can handle that if (pSaveNode && pSaveNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout()))
{
DeleteMark();
RestoreSavePos(); returntrue; // we need a frame
}
}
}
// is the cursor allowed to be in a protected node? if( !( SwCursorSelOverFlags::ChangePos & eFlags ) && !IsAtValidPos() )
{
DeleteMark();
RestoreSavePos(); returntrue;
}
if( !HasMark() ) returnfalse;
// check for invalid sections if( !::CheckNodesRange( GetMark()->GetNode(), GetPoint()->GetNode(), true ))
{
DeleteMark();
RestoreSavePos(); returntrue; // we need a frame
}
pNd = &GetMark()->GetNode(); if( pNd->IsContentNode()
&& !static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
&& !dynamic_cast<SwUnoCursor*>(this) )
{
DeleteMark();
RestoreSavePos(); returntrue; // we need a frame
}
// ensure that selection is only inside an InputField or contains the InputField completely
{ const SwTextAttr* pInputFieldTextAttrAtPoint = InputFieldAtPos(GetPoint()); const SwTextAttr* pInputFieldTextAttrAtMark = InputFieldAtPos(GetMark());
const SwTableNode* pPtNd = GetPoint()->GetNode().FindTableNode(); const SwTableNode* pMrkNd = GetMark()->GetNode().FindTableNode(); // both in no or in same table node if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd ) returnfalse;
// in different tables or only mark in table if( pMrkNd )
{ // not allowed, so go back to old position
RestoreSavePos(); // Cursor stays at old position returntrue;
}
// Note: this cannot happen in TableMode // Only Point in Table then go behind/in front of table if (SwCursorSelOverFlags::ChangePos & eFlags)
{ bool bSelTop = GetPoint()->GetNodeIndex() <
((SwCursorSelOverFlags::Toggle & eFlags)
? m_vSavePos.back().nNode : GetMark()->GetNodeIndex());
do { // loop for table after table
SwNodeOffset nSEIdx = pPtNd->EndOfSectionIndex();
SwNodeOffset nSttEndTable = nSEIdx + 1;
// No table, no protected cell: const SwTableNode* pTableNode = pCNd->FindTableNode(); if ( !pTableNode ) returnfalse;
// Current position == last save position? if (m_vSavePos.back().nNode == GetPoint()->GetNodeIndex()) returnfalse;
// Check for covered cell: bool bInCoveredCell = false; const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
OSL_ENSURE( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" ); const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTableBox( pTmpSttNode->GetIndex() ) : nullptr; //Robust #151355 if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
bInCoveredCell = true;
// Positions of covered cells are not acceptable: if ( !bInCoveredCell )
{ // Position not protected? if ( !pCNd->IsProtect() ) returnfalse;
// Cursor in protected cells allowed? if ( IsReadOnlyAvailable() ) returnfalse;
}
// If we reach this point, we are in a protected or covered table cell!
if( !bMove )
{ if( bChgCursor ) // restore the last save position
RestoreSavePos();
returntrue; // Cursor stays at old position
}
// We are in a protected table cell. Traverse top to bottom? if (m_vSavePos.back().nNode < GetPoint()->GetNodeIndex())
{ // search next valid box // if there is another StartNode after the EndNode of a cell then // there is another cell
SwNodeIndex aCellStt( *GetPointNode().FindTableBoxStartNode()->EndOfSectionNode(), 1 ); bool bProt = true;
GoNextCell: for (;;) { if( !aCellStt.GetNode().IsStartNode() ) break;
++aCellStt;
pCNd = aCellStt.GetNode().GetContentNode(); if( !pCNd )
pCNd = SwNodes::GoNext(&aCellStt);
bProt = pCNd->IsProtect(); if( !bProt ) break;
aCellStt.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
}
SetNextCursor: if( !bProt ) // found free cell
{
GetPoint()->Assign( aCellStt );
SwContentNode* pTmpCNd = GetPointContentNode(); if( pTmpCNd )
{
GetPoint()->SetContent( 0 ); returnfalse;
} return IsSelOvr( SwCursorSelOverFlags::Toggle |
SwCursorSelOverFlags::ChangePos );
} // end of table, so go to next node
++aCellStt;
SwNode* pNd = &aCellStt.GetNode(); if( pNd->IsEndNode() || HasMark())
{ // if only table in FlyFrame or SSelection then stay on old position if( bChgCursor )
RestoreSavePos(); returntrue;
} elseif( pNd->IsTableNode() )
{
++aCellStt; goto GoNextCell;
}
bProt = false; // index is now on a content node goto SetNextCursor;
}
// search for the previous valid box
{ // if there is another EndNode in front of the StartNode than there // exists a previous cell
SwNodeIndex aCellStt( *GetPointNode().FindTableBoxStartNode(), -1 );
SwNode* pNd; bool bProt = true;
GoPrevCell: for (;;) {
pNd = &aCellStt.GetNode(); if( !pNd->IsEndNode() ) break;
aCellStt.Assign( *pNd->StartOfSectionNode(), +1 );
pCNd = aCellStt.GetNode().GetContentNode(); if( !pCNd )
pCNd = SwNodes::GoNext(&aCellStt);
bProt = pCNd->IsProtect(); if( !bProt ) break;
aCellStt.Assign( *pNd->FindTableBoxStartNode(), -1 );
}
SetPrevCursor: if( !bProt ) // found free cell
{
GetPoint()->Assign( aCellStt );
SwContentNode* pTmpCNd = GetPointContentNode(); if( pTmpCNd )
{
GetPoint()->SetContent( 0 ); returnfalse;
} return IsSelOvr( SwCursorSelOverFlags::Toggle |
SwCursorSelOverFlags::ChangePos );
} // at the beginning of a table, so go to next node
--aCellStt;
pNd = &aCellStt.GetNode(); if( pNd->IsStartNode() || HasMark() )
{ // if only table in FlyFrame or SSelection then stay on old position if( bChgCursor )
RestoreSavePos(); returntrue;
} elseif( pNd->StartOfSectionNode()->IsTableNode() )
{
--aCellStt; goto GoPrevCell;
}
bProt = false; // index is now on a content node goto SetPrevCursor;
}
}
/// Return <true> if cursor can be set to this position bool SwCursor::IsAtValidPos( bool bPoint ) const
{ const SwDoc& rDoc = GetDoc(); const SwPosition* pPos = bPoint ? GetPoint() : GetMark(); const SwNode* pNd = &pPos->GetNode();
bool bEnd = false; do {
aRegion.SetMark(); // independent from search direction: SPoint is always bigger than mark // if the search area is valid
SwPosition *pSttPos = aRegion.GetMark(),
*pEndPos = aRegion.GetPoint();
*pSttPos = *pTmpCursor->Start();
*pEndPos = *pTmpCursor->End(); if( bSrchBkwrd )
aRegion.Exchange();
// as long as found and not at same position while( *pSttPos <= *pEndPos )
{
nFndRet = rParas.DoFind(*pCurrentCursor, fnMove, aRegion, bInReadOnly, xSearchItem); if( 0 == nFndRet ||
( pFndRing &&
*pFndRing->GetPoint() == *pCurrentCursor->GetPoint() &&
*pFndRing->GetMark() == *pCurrentCursor->GetMark() )) break; if( !( FIND_NO_RING & nFndRet ))
{ // #i24084# - create ring similar to the one in CreateCursor
SwCursor* pNew = pCurrentCursor->Create( pFndRing ); if( !pFndRing )
pFndRing = pNew;
if( bSrchBkwrd ) // move pEndPos in front of the found area
*pEndPos = *pCurrentCursor->Start(); else // move pSttPos behind the found area
*pSttPos = *pCurrentCursor->End();
if( *pSttPos == *pEndPos ) // in area but at the end => done break;
// this method "searches" for all use cases because in SwFindParas is always the // correct parameters and respective search method
sal_Int32 SwCursor::FindAll( SwFindParas& rParas,
SwDocPositions nStart, SwDocPositions nEnd,
FindRanges eFndRngs, bool& bCancel )
{
bCancel = false;
SwCursorSaveState aSaveState( *this );
// create region without adding it to the ring
SwPaM aRegion( *GetPoint() );
SwMoveFnCollection const & fnMove = MakeFindRange( nStart, nEnd, &aRegion );
// search in sections? if( FindRanges::InSel & eFndRngs )
{ // if string was not found in region then get all sections (cursors // stays unchanged)
nFound = lcl_FindSelection( rParas, this, fnMove,
pFndRing, aRegion, eFndRngs,
bInReadOnly, bCancel ); if( 0 == nFound ) return nFound;
// found string at least once; it's all in new Cursor ring thus delete old one while( GetNext() != this ) delete GetNext();
*GetPoint() = *pFndRing->GetPoint();
SetMark();
*GetMark() = *pFndRing->GetMark();
pFndRing->GetRingContainer().merge( GetRingContainer() ); delete pFndRing;
} elseif( FindRanges::InOther & eFndRngs )
{ // put cursor as copy of current into ring // chaining points always to first created, so forward
SwCursor* pSav = Create( this ); // save the current cursor
// if already outside of body text search from this position or start at // 1. base section if( bMvBkwrd
? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
*rNds.GetEndOfPostIts().StartOfSectionNode(),
*this, rNds.GetEndOfExtras().GetIndex() >=
GetPoint()->GetNodeIndex() )
: lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
rNds.GetEndOfExtras(), *this,
rNds.GetEndOfExtras().GetIndex() >=
GetPoint()->GetNodeIndex() ))
{
nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
aRegion, eFndRngs, bInReadOnly, bCancel );
}
if( !nFound )
{ // put back the old one
*GetPoint() = *pSav->GetPoint(); if( pSav->HasMark() )
{
SetMark();
*GetMark() = *pSav->GetMark();
} else
DeleteMark(); return 0;
}
if( !( FindRanges::InSelAll & eFndRngs ))
{ // there should only be a single one, thus add it // independent from search direction: SPoint is always bigger than // mark if the search area is valid
*GetPoint() = *pFndRing->GetPoint();
SetMark();
*GetMark() = *pFndRing->GetMark();
} else
{ // found string at least once; it's all in new Cursor ring thus delete old one while( GetNext() != this ) delete GetNext();
*GetPoint() = *pFndRing->GetPoint();
SetMark();
*GetMark() = *pFndRing->GetMark();
pFndRing->GetRingContainer().merge( GetRingContainer() );
} delete pFndRing;
} elseif( FindRanges::InSelAll & eFndRngs )
{
SwCursor* pSav = Create( this ); // save the current cursor
if( !nFound )
{ // put back the old one
*GetPoint() = *pSav->GetPoint(); if( pSav->HasMark() )
{
SetMark();
*GetMark() = *pSav->GetMark();
} else
DeleteMark(); return 0;
} while( GetNext() != this ) delete GetNext();
*GetPoint() = *pFndRing->GetPoint();
SetMark();
*GetMark() = *pFndRing->GetMark();
pFndRing->GetRingContainer().merge( GetRingContainer() ); delete pFndRing;
} else
{ // if a GetMark is set then keep the GetMark of the found object // This allows spanning an area with this search.
SwPosition aMarkPos( *GetMark() ); constbool bMarkPos = HasMark() && (eFndRngs == FindRanges::InBody);
short SwCursor::MaxReplaceArived()
{ return RET_YES;
}
namespace {
struct HideWrapper
{ // either the frame's text or the node's text (possibly pre-filtered)
OUString const* m_pText; // this is actually a TextFrameIndex but all of the i18n code uses sal_Int32
sal_Int32 m_nPtIndex; // if mapping is needed, use this frame
SwTextFrame * m_pFrame; // input in the constructor, output (via mapping) in the destructor
SwTextNode *& m_rpTextNode;
sal_Int32 & m_rPtPos;
if (comphelper::LibreOfficeKit::isActive() && aBndry.startPos == aBndry.endPos && w.m_nPtIndex > 0)
{ // nPtPos is the end of the paragraph, select the last word then.
--w.m_nPtIndex;
w.AssignBack(pTextNd, nPtPos);
switch ( eMoveType )
{ case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
*w.m_pText, w.m_nPtIndex,
g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos))); break; case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
*w.m_pText, w.m_nPtIndex,
g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos))); break; case NEXT_SENT:
{
w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
*w.m_pText, w.m_nPtIndex,
g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos))); if (w.m_nPtIndex >= 0 && w.m_nPtIndex < w.m_pText->getLength())
{ do
{
++w.m_nPtIndex;
} while (w.m_nPtIndex < w.m_pText->getLength()
&& (*w.m_pText)[w.m_nPtIndex] == ' ');
} break;
} case PREV_SENT:
w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
*w.m_pText, w.m_nPtIndex,
g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
if (w.m_nPtIndex == 0) returnfalse; // the previous sentence is not in this paragraph if (w.m_nPtIndex > 0)
{
w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
*w.m_pText, w.m_nPtIndex - 1,
g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
} break;
}
}
// it is allowed to place the PaM just behind the last // character in the text thus <= ...Len if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0)
{
GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() )
bRet = true;
}
} return bRet;
}
// it is allowed to place the PaM just behind the last // character in the text thus <= ...Len if (nStartPos <= pStartNd->GetText().getLength() && nStartPos >= 0)
{
GetMark()->Assign(*pStartNd, nStartPos);
} if (nEndPos <= pEndNd->GetText().getLength() && nEndPos >= 0)
{
GetPoint()->Assign(*pEndNd, nEndPos);
}
}
if ( !Move( fnMove, fnGo ) )
{ const SwEditShell* pSh = GetDoc().GetEditShell(); const SwViewOption* pViewOptions = pSh ? pSh->GetViewOptions() : nullptr; if (pViewOptions && pViewOptions->IsShowOutlineContentVisibilityButton())
{ // Fixes crash that occurs in documents with outline content folded at the end of // the document. When the cursor is at the end of the visible document and // right arrow key is pressed Move fails after moving the cursor to the // end of the document model, which doesn't have a node frame and causes // weird numbers to be displayed in the statusbar page number count. Left // arrow, when in this state, causes a crash without RestoredSavePos() added here.
RestoreSavePos();
} break;
}
if (pFrame)
{
SwTextFrame const* pNewFrame = GetTextFrame(GetPoint()->GetNode(), pLayout); // sw_redlinehide: fully redline-deleted nodes don't have frames... if (pFrame == pNewFrame || !pNewFrame)
{ if (!pNewFrame || beforeIndex == pFrame->MapModelToViewPos(*GetPoint()))
{ continue; // moving inside delete redline, doesn't count...
}
} else
{ // assume iteration is stable & returns the same frame
assert(!pFrame->IsAnFollow(pNewFrame) && !pNewFrame->IsAnFollow(pFrame));
pFrame = pNewFrame;
}
}
if (isFieldNames)
{
SwTextNode const*const pNode(GetPoint()->GetNode().GetTextNode());
assert(pNode);
SwTextAttr const*const pInputField(pNode->GetTextAttrAt(
GetPoint()->GetContentIndex(), RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent)); if (pInputField)
{ continue; // skip over input fields
}
}
// If we were located inside a covered cell but our position has been // corrected, we check if the last move has moved the cursor to a // different table cell. In this case we set the cursor to the stored // covered position and redo the move: if (m_nRowSpanOffset)
{ const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode(); const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : nullptr; const SwNode* pNewTabBoxSttNode = GetPoint()->GetNode().FindTableBoxStartNode(); const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : nullptr;
if ( nCurrLevel % 2 != nPrevLevel % 2 )
{ // set cursor level to the lower of the two levels
SetCursorBidiLevel( std::min( nCurrLevel, nPrevLevel ) );
} else
SetCursorBidiLevel( nCurrLevel );
}
// If the point/mark of the table cursor in the same box then set cursor to // beginning of the box if( pTableCursor && GetPointNode().StartOfSectionNode() ==
GetMarkNode().StartOfSectionNode() )
{ if ( End() != GetPoint() )
Exchange();
bAdjustTableCursor = true;
}
// It is allowed to move footnotes in other footnotes but not sections constbool bChkRange = !pFrame->IsInFootnote() || HasMark(); const SwPosition aOldPos( *GetPoint() ); constbool bInReadOnly = IsReadOnlyAvailable();
if ( bAdjustTableCursor && !bUp )
{ // Special case: We have a table cursor but the start box has more // than one paragraph. If we want to go down, we have to set the // point to the last frame in the table box. This is only necessary // if we do not already have a table selection const SwStartNode* pTableNd = GetPointNode().FindTableBoxStartNode();
OSL_ENSURE( pTableNd, "pTableCursor without SwTableNode?" );
// iterate over whole number of items? if( !nCnt && !IsSelOvr( SwCursorSelOverFlags::Toggle |
SwCursorSelOverFlags::ChangePos ) )
{ if( !pTableCursor )
{ // try to position the cursor at half of the char-rect's height
DisableCallbackAction a(rLayout);
std::pair<Point, bool> const tmp(aPt, true);
pFrame = GetPointContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp);
SwCursorMoveState eTmpState( CursorMoveState::UpDown );
eTmpState.m_bSetInReadOnly = bInReadOnly;
SwRect aTmpRect;
pFrame->GetCharRect( aTmpRect, *GetPoint(), &eTmpState ); if ( pFrame->IsVertical() )
{
aPt.setX(aTmpRect.Center().getX());
pFrame->Calc(rLayout.GetCurrShell()->GetOut());
aPt.setY(pFrame->getFrameArea().Top() + nUpDownX);
} else
{
aPt.setY(aTmpRect.Center().getY());
pFrame->Calc(rLayout.GetCurrShell()->GetOut());
aPt.setX(pFrame->getFrameArea().Left() + nUpDownX);
}
pFrame->GetModelPositionForViewPoint( GetPoint(), aPt, &eTmpState );
}
bRet = !IsSelOvr( SwCursorSelOverFlags::Toggle | SwCursorSelOverFlags::ChangePos );
} elseif (!pFrame->IsInFootnote()) // tdf#150457 Jump to the begin/end // of the first/last line only if the // cursor is not inside a footnote
{
sal_Int32 nOffset = 0;
// Jump to beginning or end of line when the cursor at first or last line. if(!bUp)
{
SwTextNode* pTextNd = GetPoint()->GetNode().GetTextNode(); if (pTextNd)
nOffset = pTextNd->GetText().getLength();
} const SwPosition aPos(*GetPointContentNode(), nOffset);
//if cursor has already been at start or end of file, //Update cursor to change nUpDownX. if ( aOldPos.GetContentIndex() == nOffset )
{ if (SwEditShell* pSh = GetDoc().GetEditShell())
pSh->UpdateCursor();
bRet = false;
} else{
*GetPoint() = aPos; // just give a new position
bRet = true;
}
// If there is another EndNode in front of the cell's StartNode then there // exists a previous cell
SwCursorSaveState aSave( *this );
SwPosition& rPtPos = *GetPoint();
// Check if we have to move the cursor to a covered cell before // proceeding: if (m_nRowSpanOffset)
{ if ( pTableBox && pTableBox->getRowSpan() > 1 )
{
pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset));
rPtPos.Assign( *pTableBox->GetSttNd() );
pTableBoxStartNode = rPtPos.GetNode().FindTableBoxStartNode();
}
m_nRowSpanOffset = 0;
}
bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPosPara )
{ // for optimization test something before const SwNode* pNd = &GetPoint()->GetNode(); bool bShortCut = false; if ( fnWhichPara == GoCurrPara )
{ // #i41048# // If fnWhichPara == GoCurrPara then (*fnWhichPara)( *this, fnPosPara ) // can already move the cursor to a different text node. In this case // we better check if IsSelOvr(). const SwContentNode* pContentNd = pNd->GetContentNode(); if ( pContentNd )
{ const sal_Int32 nSttEnd = &fnPosPara == &fnMoveForward ? 0 : pContentNd->Len(); if ( GetPoint()->GetContentIndex() != nSttEnd )
bShortCut = true;
}
} else
{ if ( pNd->IsTextNode() &&
pNd->GetNodes()[ pNd->GetIndex() +
SwNodeOffset(fnWhichPara == GoNextPara ? 1 : -1 ) ]->IsTextNode() )
bShortCut = true;
}
if ( bShortCut ) return (*fnWhichPara)( *this, fnPosPara );
// else we must use the SaveStructure, because the next/prev is not // a same node type.
SwCursorSaveState aSave( *this ); return (*fnWhichPara)( *this, fnPosPara ) &&
!IsInProtectTable( true ) &&
!IsSelOvr( SwCursorSelOverFlags::Toggle |
SwCursorSelOverFlags::ChangePos );
}
void SwCursor::RestoreSavePos()
{ // This method is not supposed to be used in cases when nodes may be // deleted; detect such cases, but do not crash (example: fdo#40831).
SwNodeOffset uNodeCount(GetPoint()->GetNodes().Count());
OSL_ENSURE(m_vSavePos.empty() || m_vSavePos.back().nNode < uNodeCount, "SwCursor::RestoreSavePos: invalid node: " "probably something was deleted; consider using SwUnoCursor instead"); if (m_vSavePos.empty() || m_vSavePos.back().nNode >= uNodeCount) return;
bool SwCursor::IsInHyphenatedWord(SwRootFrame const& rLayout) const
{ // skip, if the selected text contains multiple nodes, long text or space, // or not in word starting or word ending positions if ( HasMark() && ( GetPoint()->GetNode() != GetMark()->GetNode() ||
abs(GetPoint()->GetContentIndex() - GetMark()->GetContentIndex()) > 100 ||
GetText().indexOf(' ') > -1 ||
!( IsStartWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) ||
IsEndWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) ) ) ) returnfalse;
// skip, if no selection and the cursor is not in a word if ( !HasMark() && !IsInWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) ) returnfalse;
/// park table cursor on the boxes' start node void SwTableCursor::ParkCursor()
{ // de-register index from text node
SwNode* pNd = &GetPoint()->GetNode(); if( !pNd->IsStartNode() )
pNd = pNd->StartOfSectionNode();
GetPoint()->Assign(*pNd);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.