summaryrefslogtreecommitdiffstats
path: root/sw/source/core/crsr/crstrvl.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sw/source/core/crsr/crstrvl.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/crsr/crstrvl.cxx')
-rw-r--r--sw/source/core/crsr/crstrvl.cxx2743
1 files changed, 2743 insertions, 0 deletions
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
new file mode 100644
index 000000000..adf761742
--- /dev/null
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -0,0 +1,2743 @@
+/* -*- 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 .
+ */
+
+#include <memory>
+#include <utility>
+#include <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <svx/svdobj.hxx>
+#include <osl/diagnose.h>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <txttxmrk.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <viscrs.hxx>
+#include "callnk.hxx"
+#include <doctxm.hxx>
+#include <docfld.hxx>
+#include <expfld.hxx>
+#include <reffld.hxx>
+#include <flddat.hxx>
+#include <cellatr.hxx>
+#include <swundo.hxx>
+#include <redline.hxx>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <pagedesc.hxx>
+#include <fesh.hxx>
+#include <charfmt.hxx>
+#include <fmturl.hxx>
+#include <txtfrm.hxx>
+#include <wrong.hxx>
+#include <calbck.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <docufld.hxx>
+#include <svx/srchdlg.hxx>
+#include <frameformats.hxx>
+#include <docsh.hxx>
+#include <wrtsh.hxx>
+#include <textcontentcontrol.hxx>
+
+using namespace ::com::sun::star;
+
+void SwCursorShell::MoveCursorToNum()
+{
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ if( ActionPend() )
+ return;
+ CurrShell aCurr( this );
+ // try to set cursor onto this position, at half of the char-
+ // SRectangle's height
+ Point aPt( m_pCurrentCursor->GetPtPos() );
+ std::pair<Point, bool> const tmp(aPt, true);
+ SwContentFrame * pFrame = m_pCurrentCursor->GetContentNode()->getLayoutFrame(
+ GetLayout(), m_pCurrentCursor->GetPoint(), &tmp);
+ pFrame->GetCharRect( m_aCharRect, *m_pCurrentCursor->GetPoint() );
+ pFrame->Calc(GetOut());
+ if( pFrame->IsVertical() )
+ {
+ aPt.setX(m_aCharRect.Center().getX());
+ aPt.setY(pFrame->getFrameArea().Top() + GetUpDownX());
+ }
+ else
+ {
+ aPt.setY(m_aCharRect.Center().getY());
+ aPt.setX(pFrame->getFrameArea().Left() + GetUpDownX());
+ }
+ pFrame->GetModelPositionForViewPoint( m_pCurrentCursor->GetPoint(), aPt );
+ if ( !m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::Toggle |
+ SwCursorSelOverFlags::ChangePos ))
+ {
+ UpdateCursor(SwCursorShell::UPDOWN |
+ SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+ SwCursorShell::READONLY );
+ }
+}
+
+/// go to next/previous point on the same level
+void SwCursorShell::GotoNextNum()
+{
+ if (!SwDoc::GotoNextNum(*m_pCurrentCursor->GetPoint(), GetLayout()))
+ return;
+ MoveCursorToNum();
+}
+
+void SwCursorShell::GotoPrevNum()
+{
+ if (!SwDoc::GotoPrevNum(*m_pCurrentCursor->GetPoint(), GetLayout()))
+ return;
+ MoveCursorToNum();
+}
+
+/// jump from content to header
+bool SwCursorShell::GotoHeaderText()
+{
+ const SwFrame* pFrame = GetCurrFrame()->FindPageFrame();
+ while( pFrame && !pFrame->IsHeaderFrame() )
+ pFrame = pFrame->GetLower();
+ // found header, search 1. content frame
+ while( pFrame && !pFrame->IsContentFrame() )
+ pFrame = pFrame->GetLower();
+
+ if( pFrame )
+ {
+ CurrShell aCurr( this );
+ // get header frame
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursor *pTmpCursor = getShellCursor( true );
+ SwCursorSaveState aSaveState( *pTmpCursor );
+ pFrame->Calc(GetOut());
+ Point aPt( pFrame->getFrameArea().Pos() + pFrame->getFramePrintArea().Pos() );
+ pFrame->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt );
+ if( !pTmpCursor->IsSelOvr() )
+ UpdateCursor();
+ else
+ pFrame = nullptr;
+ }
+ return nullptr != pFrame;
+}
+
+/// jump from content to footer
+bool SwCursorShell::GotoFooterText()
+{
+ const SwPageFrame* pFrame = GetCurrFrame()->FindPageFrame();
+ if( pFrame )
+ {
+ const SwFrame* pLower = pFrame->GetLastLower();
+
+ while( pLower && !pLower->IsFooterFrame() )
+ pLower = pLower->GetLower();
+ // found footer, search 1. content frame
+ while( pLower && !pLower->IsContentFrame() )
+ pLower = pLower->GetLower();
+
+ if( pLower )
+ {
+ SwCursor *pTmpCursor = getShellCursor( true );
+ CurrShell aCurr( this );
+ // get position in footer
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pTmpCursor );
+ pLower->Calc(GetOut());
+ Point aPt( pLower->getFrameArea().Pos() + pLower->getFramePrintArea().Pos() );
+ pLower->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt );
+ if( !pTmpCursor->IsSelOvr() )
+ UpdateCursor();
+ else
+ pFrame = nullptr;
+ }
+ else
+ pFrame = nullptr;
+ }
+ else
+ pFrame = nullptr;
+ return nullptr != pFrame;
+}
+
+bool SwCursorShell::SetCursorInHdFt( size_t nDescNo, bool bInHeader )
+{
+ bool bRet = false;
+ SwDoc *pMyDoc = GetDoc();
+ const SwPageDesc* pDesc = nullptr;
+
+ CurrShell aCurr( this );
+
+ if( SIZE_MAX == nDescNo )
+ {
+ // take the current one
+ const SwContentFrame *pCurrFrame = GetCurrFrame();
+ const SwPageFrame* pPage = (pCurrFrame == nullptr) ? nullptr : pCurrFrame->FindPageFrame();
+ if( pPage && pMyDoc->ContainsPageDesc(
+ pPage->GetPageDesc(), &nDescNo) )
+ pDesc = pPage->GetPageDesc();
+ }
+ else
+ if (nDescNo < pMyDoc->GetPageDescCnt())
+ pDesc = &pMyDoc->GetPageDesc( nDescNo );
+
+ if( pDesc )
+ {
+ // check if the attribute exists
+ const SwFormatContent* pCnt = nullptr;
+ if( bInHeader )
+ {
+ // mirrored pages? ignore for now
+ const SwFormatHeader& rHd = pDesc->GetMaster().GetHeader();
+ if( rHd.GetHeaderFormat() )
+ pCnt = &rHd.GetHeaderFormat()->GetContent();
+ }
+ else
+ {
+ const SwFormatFooter& rFt = pDesc->GetMaster().GetFooter();
+ if( rFt.GetFooterFormat() )
+ pCnt = &rFt.GetFooterFormat()->GetContent();
+ }
+
+ if( pCnt && pCnt->GetContentIdx() )
+ {
+ SwNodeIndex aIdx( *pCnt->GetContentIdx(), 1 );
+ SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
+ if( !pCNd )
+ pCNd = pMyDoc->GetNodes().GoNext( &aIdx );
+
+ Point aPt( m_pCurrentCursor->GetPtPos() );
+
+ std::pair<Point, bool> const tmp(aPt, false);
+ if (pCNd && nullptr != pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp))
+ {
+ // then we can set the cursor in here
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ ClearMark();
+
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+ rPos.nNode = *pCNd;
+ rPos.nContent.Assign( pCNd, 0 );
+
+ bRet = !m_pCurrentCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+ SwCursorShell::READONLY );
+ }
+ }
+ }
+ return bRet;
+}
+
+/// jump to the next index
+bool SwCursorShell::GotoNextTOXBase( const OUString* pName )
+{
+ bool bRet = false;
+
+ const SwSectionFormats& rFormats = GetDoc()->GetSections();
+ SwContentNode* pFnd = nullptr;
+ for( SwSectionFormats::size_type n = rFormats.size(); n; )
+ {
+ const SwSection* pSect = rFormats[ --n ]->GetSection();
+ if (SectionType::ToxContent == pSect->GetType())
+ {
+ SwSectionNode const*const pSectNd(
+ pSect->GetFormat()->GetSectionNode());
+ if ( pSectNd
+ && m_pCurrentCursor->GetPoint()->nNode < pSectNd->GetIndex()
+ && (!pFnd || pFnd->GetIndex() > pSectNd->GetIndex())
+ && (!pName || *pName ==
+ static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()))
+ {
+ SwNodeIndex aIdx(*pSectNd, 1);
+ SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
+ if (!pCNd)
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ if (pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex())
+ {
+ SwContentFrame const*const pCFrame(
+ pCNd->getLayoutFrame(GetLayout()));
+ if (pCFrame &&
+ (IsReadOnlyAvailable() || !pCFrame->IsProtected()))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+ }
+ }
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ m_pCurrentCursor->GetPoint()->nNode = *pFnd;
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !m_pCurrentCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ }
+ return bRet;
+}
+
+/// jump to previous index
+bool SwCursorShell::GotoPrevTOXBase( const OUString* pName )
+{
+ bool bRet = false;
+
+ const SwSectionFormats& rFormats = GetDoc()->GetSections();
+ SwContentNode* pFnd = nullptr;
+ for( SwSectionFormats::size_type n = rFormats.size(); n; )
+ {
+ const SwSection* pSect = rFormats[ --n ]->GetSection();
+ if (SectionType::ToxContent == pSect->GetType())
+ {
+ SwSectionNode const*const pSectNd(
+ pSect->GetFormat()->GetSectionNode());
+ if ( pSectNd
+ && m_pCurrentCursor->GetPoint()->nNode > pSectNd->EndOfSectionIndex()
+ && (!pFnd || pFnd->GetIndex() < pSectNd->GetIndex())
+ && (!pName || *pName ==
+ static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()))
+ {
+ SwNodeIndex aIdx(*pSectNd, 1);
+ SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
+ if (!pCNd)
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ if (pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex())
+ {
+ SwContentFrame const*const pCFrame(
+ pCNd->getLayoutFrame(GetLayout()));
+ if (pCFrame &&
+ (IsReadOnlyAvailable() || !pCFrame->IsProtected()))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ m_pCurrentCursor->GetPoint()->nNode = *pFnd;
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !m_pCurrentCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ }
+ return bRet;
+}
+
+/// jump to index of TOXMark
+void SwCursorShell::GotoTOXMarkBase()
+{
+ SwTOXMarks aMarks;
+ sal_uInt16 nCnt = SwDoc::GetCurTOXMark(*m_pCurrentCursor->GetPoint(), aMarks);
+ if(!nCnt)
+ return;
+ // Take the 1. and get the index type. Ask it for the actual index.
+ const SwTOXType* pType = aMarks[0]->GetTOXType();
+ auto pContentFrame = pType->FindContentFrame(*GetDoc(), *GetLayout());
+ SwCallLink aLk(*this); // watch Cursor-Moves
+ SwCursorSaveState aSaveState(*m_pCurrentCursor);
+ assert(pContentFrame->IsTextFrame());
+ *m_pCurrentCursor->GetPoint() = static_cast<SwTextFrame const*>(pContentFrame)->MapViewToModelPos(TextFrameIndex(0));
+ if(!m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr())
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+}
+
+/// Jump to next/previous table formula
+/// Optionally it is possible to also jump to broken formulas
+bool SwCursorShell::GotoNxtPrvTableFormula( bool bNext, bool bOnlyErrors )
+{
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+
+ if( IsTableMode() )
+ return false;
+
+ bool bFnd = false;
+ SwPosition aOldPos = *m_pCurrentCursor->GetPoint();
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = SwNodeOffset(0);
+ SetGetExpField aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ {
+ const SwNode* pSttNd = rPos.nNode.GetNode().FindTableBoxStartNode();
+ if( pSttNd )
+ {
+ const SwTableBox* pTBox = pSttNd->FindTableNode()->GetTable().
+ GetTableBox( pSttNd->GetIndex() );
+ if( pTBox )
+ aCurGEF = SetGetExpField( *pTBox );
+ }
+ }
+
+ if( rPos.nNode < GetDoc()->GetNodes().GetEndOfExtras() )
+ {
+ // also at collection use only the first frame
+ std::pair<Point, bool> const tmp(aPt, false);
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().GetContentNode()->getLayoutFrame( GetLayout(),
+ &rPos, &tmp) );
+ }
+ {
+ sal_uInt32 nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
+
+ if( nMaxItems > 0 )
+ {
+ sal_uInt8 nMaxDo = 2;
+ do {
+ for (const SfxPoolItem* pItem : GetDoc()->GetAttrPool().GetItemSurrogates(RES_BOXATR_FORMULA))
+ {
+ const SwTableBox* pTBox;
+ auto pFormulaItem = dynamic_cast<const SwTableBoxFormula*>(pItem);
+ if( !pFormulaItem )
+ continue;
+ pTBox = pFormulaItem->GetTableBox();
+ if( pTBox &&
+ pTBox->GetSttNd() &&
+ pTBox->GetSttNd()->GetNodes().IsDocNodes() &&
+ ( !bOnlyErrors ||
+ !pFormulaItem->HasValidBoxes() ) )
+ {
+ SwNodeIndex aIdx( *pTBox->GetSttNd() );
+ const SwContentNode* pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ std::pair<Point, bool> const tmp(aPt, false);
+ if (pCNd)
+ {
+ const SwContentFrame* pCFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pCFrame && (IsReadOnlyAvailable() || !pCFrame->IsProtected() ))
+ {
+ SetGetExpField aCmp( *pTBox );
+ aCmp.SetBodyPos( *pCFrame );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = true;
+ }
+ }
+ }
+ }
+ }
+ if( !bFnd )
+ {
+ if( bNext )
+ {
+ rPos.nNode = SwNodeOffset(0);
+ rPos.nContent = 0;
+ aCurGEF = SetGetExpField( rPos );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
+ }
+ else
+ {
+ aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
+ }
+ }
+ } while( !bFnd && --nMaxDo );
+ }
+ }
+
+ if( bFnd )
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ aFndGEF.GetPosOfContent( rPos );
+ m_pCurrentCursor->DeleteMark();
+
+ bFnd = !m_pCurrentCursor->IsSelOvr();
+ if( bFnd )
+ UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+ SwCursorShell::READONLY );
+ }
+ else
+ {
+ rPos = aOldPos;
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ }
+
+ return bFnd;
+}
+
+/// jump to next/previous index marker
+bool SwCursorShell::GotoNxtPrvTOXMark( bool bNext )
+{
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+
+ if( IsTableMode() )
+ return false;
+
+ bool bFnd = false;
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = SwNodeOffset(0);
+ SetGetExpField aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ if( rPos.nNode.GetIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // also at collection use only the first frame
+ std::pair<Point, bool> const tmp(aPt, false);
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().
+ GetContentNode()->getLayoutFrame(GetLayout(), &rPos, &tmp));
+ }
+
+ {
+ const SwTextNode* pTextNd;
+ const SwTextTOXMark* pTextTOX;
+ sal_uInt32 nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
+
+ if( nMaxItems > 0 )
+ {
+ do {
+ for (const SfxPoolItem* pItem : GetDoc()->GetAttrPool().GetItemSurrogates(RES_TXTATR_TOXMARK))
+ {
+ auto pToxMarkItem = dynamic_cast<const SwTOXMark*>(pItem);
+ if( !pToxMarkItem )
+ continue;
+ pTextTOX = pToxMarkItem->GetTextTOXMark();
+ if( !pTextTOX )
+ continue;
+ pTextNd = &pTextTOX->GetTextNode();
+ if( !pTextNd->GetNodes().IsDocNodes() )
+ continue;
+ std::pair<Point, bool> const tmp(aPt, false);
+ const SwContentFrame* pCFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if( pCFrame && ( IsReadOnlyAvailable() || !pCFrame->IsProtected() ))
+ {
+ SwNodeIndex aNdIndex( *pTextNd ); // UNIX needs this object
+ SetGetExpField aCmp( aNdIndex, *pTextTOX );
+ aCmp.SetBodyPos( *pCFrame );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = true;
+ }
+ }
+ }
+ if( !bFnd )
+ {
+ if ( bNext )
+ {
+ rPos.nNode = SwNodeOffset(0);
+ rPos.nContent = 0;
+ aCurGEF = SetGetExpField( rPos );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
+ }
+ else
+ {
+ aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) );
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
+ }
+ }
+ } while ( !bFnd );
+ }
+ else
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ }
+
+ if( bFnd )
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ aFndGEF.GetPosOfContent( rPos );
+
+ bFnd = !m_pCurrentCursor->IsSelOvr();
+ if( bFnd )
+ UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+ SwCursorShell::READONLY );
+ }
+ return bFnd;
+}
+
+/// traveling between marks
+const SwTOXMark& SwCursorShell::GotoTOXMark( const SwTOXMark& rStart,
+ SwTOXSearch eDir )
+{
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ const SwTOXMark& rNewMark = GetDoc()->GotoTOXMark( rStart, eDir,
+ IsReadOnlyAvailable() );
+ // set position
+ SwPosition& rPos = *GetCursor()->GetPoint();
+ rPos.nNode = rNewMark.GetTextTOXMark()->GetTextNode();
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetContentNode(),
+ rNewMark.GetTextTOXMark()->GetStart() );
+
+ if( !m_pCurrentCursor->IsSelOvr() )
+ UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+ SwCursorShell::READONLY );
+
+ return rNewMark;
+}
+
+/// jump to next/previous field type
+static void lcl_MakeFieldLst(
+ SetGetExpFields& rLst,
+ const SwFieldType& rFieldType,
+ const bool bInReadOnly,
+ const bool bChkInpFlag = false )
+{
+ // always search the 1. frame
+ Point aPt;
+ std::vector<SwFormatField*> vFields;
+ rFieldType.GatherFields(vFields, false);
+ for(SwFormatField* pFormatField: vFields)
+ {
+ SwTextField* pTextField = pFormatField->GetTextField();
+ if ( pTextField != nullptr
+ && ( !bChkInpFlag
+ || static_cast<const SwSetExpField*>(pTextField->GetFormatField().GetField())->GetInputFlag() ) )
+ {
+ const SwTextNode& rTextNode = pTextField->GetTextNode();
+ std::pair<Point, bool> const tmp(aPt, false);
+ const SwContentFrame* pCFrame =
+ rTextNode.getLayoutFrame(
+ rTextNode.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
+ nullptr, &tmp);
+ if ( pCFrame != nullptr
+ && ( bInReadOnly || !pCFrame->IsProtected() ) )
+ {
+ std::unique_ptr<SetGetExpField> pNew(new SetGetExpField( SwNodeIndex( rTextNode ), pTextField ));
+ pNew->SetBodyPos( *pCFrame );
+ rLst.insert( std::move(pNew) );
+ }
+ }
+ }
+}
+
+static SetGetExpFields::const_iterator
+lcl_FindField(bool & o_rFound, SetGetExpFields const& rSrtLst,
+ SwRootFrame const *const pLayout, SwTextNode *const pTextNode,
+ SwTextField const *const pTextField, SwPosition const& rPos,
+ sal_Int32 const nContentOffset)
+{
+ std::unique_ptr<SetGetExpField> pSrch;
+ std::unique_ptr<SwIndex> pIndex;
+ if (-1 == nContentOffset)
+ {
+ pSrch.reset(new SetGetExpField(rPos.nNode, pTextField, &rPos.nContent));
+ }
+ else
+ {
+ pIndex.reset(new SwIndex(rPos.nNode.GetNode().GetContentNode(), nContentOffset));
+ pSrch.reset(new SetGetExpField(rPos.nNode, pTextField, pIndex.get()));
+ }
+
+ if (rPos.nNode.GetIndex() < pTextNode->GetNodes().GetEndOfExtras().GetIndex())
+ {
+ // also at collection use only the first frame
+ Point aPt;
+ std::pair<Point, bool> const tmp(aPt, false);
+ pSrch->SetBodyPos(*pTextNode->getLayoutFrame(pLayout, &rPos, &tmp));
+ }
+
+ SetGetExpFields::const_iterator it = rSrtLst.lower_bound(pSrch.get());
+
+ o_rFound = (it != rSrtLst.end()) && (**it == *pSrch);
+ return it;
+}
+
+bool SwCursorShell::MoveFieldType(
+ const SwFieldType* pFieldType,
+ const bool bNext,
+ const SwFieldIds nResType,
+ const bool bAddSetExpressionFieldsToInputFields )
+{
+ // sorted list of all fields
+ SetGetExpFields aSrtLst;
+
+ if ( pFieldType )
+ {
+ if( SwFieldIds::Input != pFieldType->Which() && !pFieldType->HasWriterListeners() )
+ {
+ return false;
+ }
+
+ // found Modify object, add all fields to array
+ ::lcl_MakeFieldLst( aSrtLst, *pFieldType, IsReadOnlyAvailable() );
+
+ if( SwFieldIds::Input == pFieldType->Which() && bAddSetExpressionFieldsToInputFields )
+ {
+ // there are hidden input fields in the set exp. fields
+ const SwFieldTypes& rFieldTypes = *mxDoc->getIDocumentFieldsAccess().GetFieldTypes();
+ const size_t nSize = rFieldTypes.size();
+ for( size_t i=0; i < nSize; ++i )
+ {
+ pFieldType = rFieldTypes[ i ].get();
+ if ( SwFieldIds::SetExp == pFieldType->Which() )
+ {
+ ::lcl_MakeFieldLst( aSrtLst, *pFieldType, IsReadOnlyAvailable(), true );
+ }
+ }
+ }
+ }
+ else
+ {
+ const SwFieldTypes& rFieldTypes = *mxDoc->getIDocumentFieldsAccess().GetFieldTypes();
+ const size_t nSize = rFieldTypes.size();
+ const bool bAllFieldTypes = nResType == SwFieldIds::Unknown;
+ for( size_t i=0; i < nSize; ++i )
+ {
+ pFieldType = rFieldTypes[ i ].get();
+ if (bAllFieldTypes || nResType == pFieldType->Which())
+ {
+ ::lcl_MakeFieldLst( aSrtLst, *pFieldType, IsReadOnlyAvailable() );
+ }
+ }
+ }
+
+ // found no fields?
+ if( aSrtLst.empty() )
+ return false;
+
+ SetGetExpFields::const_iterator it;
+ SwCursor* pCursor = getShellCursor( true );
+ {
+ // (1998): Always use field for search so that the right one is found as
+ // well some are in frames that are anchored to a paragraph that has a
+ // field
+ const SwPosition& rPos = *pCursor->GetPoint();
+
+ SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
+ OSL_ENSURE( pTNd, "No ContentNode" );
+
+ SwTextField * pTextField = pTNd->GetFieldTextAttrAt( rPos.nContent.GetIndex(), true );
+ const bool bDelField = ( pTextField == nullptr );
+ sal_Int32 nContentOffset = -1;
+
+ if( bDelField )
+ {
+ // create dummy for the search
+ SwFormatField* pFormatField = new SwFormatField( SwDateTimeField(
+ static_cast<SwDateTimeFieldType*>(mxDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::DateTime ) ) ) );
+
+ pTextField = new SwTextField( *pFormatField, rPos.nContent.GetIndex(),
+ mxDoc->IsClipBoard() );
+ pTextField->ChgTextNode( pTNd );
+ }
+ else
+ {
+ // the cursor might be anywhere inside the input field,
+ // but we will be searching for the field start
+ if (pTextField->Which() == RES_TXTATR_INPUTFIELD
+ && rPos.nContent.GetIndex() != pTextField->GetStart())
+ nContentOffset = pTextField->GetStart();
+ }
+ bool isSrch;
+ it = lcl_FindField(isSrch, aSrtLst,
+ GetLayout(), pTNd, pTextField, rPos, nContentOffset);
+
+ if( bDelField )
+ {
+ auto const pFormat(static_cast<SwFormatField*>(&pTextField->GetAttr()));
+ delete pTextField;
+ delete pFormat;
+ }
+
+ if( it != aSrtLst.end() && isSrch ) // found
+ {
+ if( bNext )
+ {
+ if( ++it == aSrtLst.end() )
+ return false; // already at the end
+ }
+ else
+ {
+ if( it == aSrtLst.begin() )
+ return false; // no more steps backward possible
+ --it;
+ }
+ }
+ else // not found
+ {
+ if( bNext )
+ {
+ if( it == aSrtLst.end() )
+ return false;
+ }
+ else
+ {
+ if( it == aSrtLst.begin() )
+ return false; // no more steps backward possible
+ --it;
+ }
+ }
+ }
+ const SetGetExpField& rFnd = **it;
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+
+ rFnd.GetPosOfContent( *pCursor->GetPoint() );
+ bool bRet = !m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
+ SwCursorSelOverFlags::Toggle );
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return bRet;
+}
+
+bool SwCursorShell::GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote)
+{
+ if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this))
+ pWrtSh->addCurrentPosition();
+
+ bool bRet = false;
+ SwCursor* pCursor = getShellCursor(true);
+
+ CurrShell aCurr(this);
+ SwCallLink aLk(*this); // watch Cursor-Moves
+ SwCursorSaveState aSaveState(*pCursor);
+
+ pCursor->GetPoint()->nNode = rTextFootnote.GetTextNode();
+ pCursor->GetPoint()->nContent.Assign(const_cast<SwTextNode*>(&rTextFootnote.GetTextNode()),
+ rTextFootnote.GetStart());
+ bRet = !pCursor->IsSelOvr();
+ if (bRet)
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return bRet;
+}
+
+bool SwCursorShell::GotoFormatContentControl(const SwFormatContentControl& rContentControl)
+{
+ bool bRet = false;
+ std::shared_ptr<SwContentControl> pContentControl = rContentControl.GetContentControl();
+ if (!pContentControl->GetShowingPlaceHolder() && !pContentControl->GetCheckbox()
+ && !pContentControl->GetSelectedListItem() && !pContentControl->GetSelectedDate())
+ {
+ return bRet;
+ }
+
+ const SwTextContentControl* pTextContentControl = pContentControl->GetTextAttr();
+ if (pTextContentControl)
+ {
+ CurrShell aCurr(this);
+ SwCallLink aLink(*this);
+
+ SwCursor* pCursor = getShellCursor(true);
+ SwCursorSaveState aSaveState(*pCursor);
+
+ pCursor->SetMark();
+ SwTextNode* pTextNode = pContentControl->GetTextNode();
+ pCursor->GetPoint()->nNode = *pTextNode;
+ // Don't select the text attribute itself at the start.
+ sal_Int32 nStart = pTextContentControl->GetStart() + 1;
+ pCursor->GetPoint()->nContent.Assign(pTextNode, nStart);
+ pCursor->GetMark()->nNode = *pTextNode;
+ // Don't select the CH_TXTATR_BREAKWORD itself at the end.
+ sal_Int32 nEnd = *pTextContentControl->End() - 1;
+ pCursor->GetMark()->nContent.Assign(pTextNode, nEnd);
+
+ // Assume that once the placeholder is selected, the content is no longer the placeholder.
+ pContentControl->SetShowingPlaceHolder(false);
+
+ bRet = !pCursor->IsSelOvr();
+ if (bRet)
+ {
+ UpdateCursor(SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE
+ | SwCursorShell::READONLY);
+ }
+ }
+
+ return bRet;
+}
+
+bool SwCursorShell::GotoFormatField( const SwFormatField& rField )
+{
+ bool bRet = false;
+ SwTextField const*const pTextField(rField.GetTextField());
+ if (pTextField
+ && (!GetLayout()->IsHideRedlines()
+ || !sw::IsFieldDeletedInModel(
+ GetDoc()->getIDocumentRedlineAccess(), *pTextField)))
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+
+ SwCursor* pCursor = getShellCursor( true );
+ SwCursorSaveState aSaveState( *pCursor );
+
+ SwTextNode* pTNd = pTextField->GetpTextNode();
+ pCursor->GetPoint()->nNode = *pTNd;
+ pCursor->GetPoint()->nContent.Assign( pTNd, pTextField->GetStart() );
+
+ bRet = !pCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ }
+ return bRet;
+}
+
+SwTextField * SwCursorShell::GetTextFieldAtPos(
+ const SwPosition* pPos,
+ const bool bIncludeInputFieldAtStart )
+{
+ SwTextField* pTextField = nullptr;
+
+ SwTextNode * const pNode = pPos->nNode.GetNode().GetTextNode();
+ if ( pNode != nullptr )
+ {
+ pTextField = pNode->GetFieldTextAttrAt( pPos->nContent.GetIndex(), bIncludeInputFieldAtStart );
+ }
+
+ return pTextField;
+}
+
+SwTextField* SwCursorShell::GetTextFieldAtCursor(
+ const SwPaM* pCursor,
+ const bool bIncludeInputFieldAtStart )
+{
+ SwTextField* pFieldAtCursor = nullptr;
+
+ SwTextField* pTextField = GetTextFieldAtPos( pCursor->Start(), bIncludeInputFieldAtStart );
+ if ( pTextField != nullptr
+ && pCursor->Start()->nNode == pCursor->End()->nNode )
+ {
+ const sal_Int32 nTextFieldLength =
+ pTextField->End() != nullptr
+ ? *(pTextField->End()) - pTextField->GetStart()
+ : 1;
+ if ( ( pCursor->End()->nContent.GetIndex() - pCursor->Start()->nContent.GetIndex() ) <= nTextFieldLength )
+ {
+ pFieldAtCursor = pTextField;
+ }
+ }
+
+ return pFieldAtCursor;
+}
+
+SwField* SwCursorShell::GetFieldAtCursor(
+ const SwPaM *const pCursor,
+ const bool bIncludeInputFieldAtStart)
+{
+ SwTextField *const pField(GetTextFieldAtCursor(pCursor, bIncludeInputFieldAtStart));
+ return pField
+ ? const_cast<SwField*>(pField->GetFormatField().GetField())
+ : nullptr;
+}
+
+SwField* SwCursorShell::GetCurField( const bool bIncludeInputFieldAtStart ) const
+{
+ SwPaM* pCursor = GetCursor();
+ if ( pCursor->IsMultiSelection() )
+ {
+ // multi selection not handled.
+ return nullptr;
+ }
+
+ SwField* pCurField = GetFieldAtCursor( pCursor, bIncludeInputFieldAtStart );
+ if ( pCurField != nullptr
+ && SwFieldIds::Table == pCurField->GetTyp()->Which() )
+ {
+ // table formula? convert internal name into external
+ const SwTableNode* pTableNd = IsCursorInTable();
+ static_cast<SwTableField*>(pCurField)->PtrToBoxNm( pTableNd ? &pTableNd->GetTable() : nullptr );
+ }
+
+ return pCurField;
+}
+
+bool SwCursorShell::CursorInsideInputField() const
+{
+ for(SwPaM& rCursor : GetCursor()->GetRingContainer())
+ {
+ if (dynamic_cast<const SwTextInputField*>(GetTextFieldAtCursor(&rCursor, true)))
+ return true;
+ }
+ return false;
+}
+
+SwTextContentControl* SwCursorShell::CursorInsideContentControl() const
+{
+ for (SwPaM& rCursor : GetCursor()->GetRingContainer())
+ {
+ const SwPosition* pStart = rCursor.Start();
+ SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode();
+ if (!pTextNode)
+ {
+ continue;
+ }
+
+ sal_Int32 nIndex = pStart->nContent.GetIndex();
+ if (SwTextAttr* pAttr = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT))
+ {
+ return static_txtattr_cast<SwTextContentControl*>(pAttr);
+ }
+ }
+
+ return nullptr;
+}
+
+bool SwCursorShell::PosInsideInputField( const SwPosition& rPos )
+{
+ return dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, false )) != nullptr;
+}
+
+bool SwCursorShell::DocPtInsideInputField( const Point& rDocPt ) const
+{
+ SwPosition aPos( *(GetCursor()->Start()) );
+ Point aDocPt( rDocPt );
+ if ( GetLayout()->GetModelPositionForViewPoint( &aPos, aDocPt ) )
+ {
+ return PosInsideInputField( aPos );
+ }
+ return false;
+}
+
+sal_Int32 SwCursorShell::StartOfInputFieldAtPos( const SwPosition& rPos )
+{
+ const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, true ));
+ assert(pTextInputField != nullptr
+ && "<SwEditShell::StartOfInputFieldAtPos(..)> - no Input Field at given position");
+ return pTextInputField->GetStart();
+}
+
+sal_Int32 SwCursorShell::EndOfInputFieldAtPos( const SwPosition& rPos )
+{
+ const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, true ));
+ assert(pTextInputField != nullptr
+ && "<SwEditShell::EndOfInputFieldAtPos(..)> - no Input Field at given position");
+ return *(pTextInputField->End());
+}
+
+void SwCursorShell::GotoOutline( SwOutlineNodes::size_type nIdx )
+{
+ SwCursor* pCursor = getShellCursor( true );
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ SwTextNode* pTextNd = rNds.GetOutLineNds()[ nIdx ]->GetTextNode();
+ pCursor->GetPoint()->nNode = *pTextNd;
+ pCursor->GetPoint()->nContent.Assign( pTextNd, 0 );
+
+ if( !pCursor->IsSelOvr() )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+}
+
+bool SwCursorShell::GotoOutline( const OUString& rName )
+{
+ SwCursor* pCursor = getShellCursor( true );
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+
+ bool bRet = false;
+ if (mxDoc->GotoOutline(*pCursor->GetPoint(), rName, GetLayout())
+ && !pCursor->IsSelOvr())
+ {
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ bRet = true;
+ }
+ return bRet;
+}
+
+/// jump to next node with outline num.
+bool SwCursorShell::GotoNextOutline()
+{
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ if ( rNds.GetOutLineNds().empty() )
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ return false;
+ }
+
+ SwCursor* pCursor = getShellCursor( true );
+ SwNode* pNd = &(pCursor->GetNode());
+ SwOutlineNodes::size_type nPos;
+ bool bUseFirst = !rNds.GetOutLineNds().Seek_Entry( pNd, &nPos );
+ SwOutlineNodes::size_type const nStartPos(nPos);
+
+ do
+ {
+ if (!bUseFirst)
+ {
+ ++nPos;
+ }
+ if (rNds.GetOutLineNds().size() <= nPos)
+ {
+ nPos = 0;
+ }
+
+ if (bUseFirst)
+ {
+ bUseFirst = false;
+ }
+ else
+ {
+ if (nPos == nStartPos)
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ return false;
+ }
+ }
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+ }
+ while (!sw::IsParaPropsNode(*GetLayout(), *pNd->GetTextNode()));
+
+ if (nPos < nStartPos)
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
+ }
+ else
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+ }
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+ pCursor->GetPoint()->nNode = *pNd;
+ pCursor->GetPoint()->nContent.Assign( pNd->GetTextNode(), 0 );
+
+ bool bRet = !pCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return bRet;
+}
+
+/// jump to previous node with outline num.
+bool SwCursorShell::GotoPrevOutline()
+{
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ if ( rNds.GetOutLineNds().empty() )
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ return false;
+ }
+
+ SwCursor* pCursor = getShellCursor( true );
+ SwNode* pNd = &(pCursor->GetNode());
+ SwOutlineNodes::size_type nPos;
+ bool bRet = false;
+ (void)rNds.GetOutLineNds().Seek_Entry(pNd, &nPos);
+ SwOutlineNodes::size_type const nStartPos(nPos);
+
+ do
+ {
+ if (nPos == 0)
+ {
+ nPos = rNds.GetOutLineNds().size() - 1;
+ }
+ else
+ {
+ --nPos; // before
+ }
+ if (nPos == nStartPos)
+ {
+ pNd = nullptr;
+ break;
+ }
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+ }
+ while (!sw::IsParaPropsNode(*GetLayout(), *pNd->GetTextNode()));
+
+ if (pNd)
+ {
+ if (nStartPos < nPos)
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
+ }
+ else
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
+ }
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+ pCursor->GetPoint()->nNode = *pNd;
+ pCursor->GetPoint()->nContent.Assign( pNd->GetTextNode(), 0 );
+
+ bRet = !pCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ }
+ else
+ {
+ SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
+ }
+ return bRet;
+}
+
+/// search "outline position" before previous outline node at given level
+SwOutlineNodes::size_type SwCursorShell::GetOutlinePos(sal_uInt8 nLevel, SwPaM* pPaM)
+{
+ SwPaM* pCursor = pPaM ? pPaM : getShellCursor(true);
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = &(pCursor->GetNode());
+ SwOutlineNodes::size_type nPos;
+ if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
+ nPos++; // is at correct position; take next for while
+
+ while( nPos-- ) // check the one in front of the current
+ {
+ pNd = rNds.GetOutLineNds()[ nPos ];
+
+ if (sw::IsParaPropsNode(*GetLayout(), *pNd->GetTextNode())
+ && pNd->GetTextNode()->GetAttrOutlineLevel()-1 <= nLevel)
+ {
+ if (pNd->GetIndex() < rNds.GetEndOfExtras().GetIndex()
+ && pCursor->GetNode().GetIndex() > rNds.GetEndOfExtras().GetIndex())
+ {
+ // node found in extras but cursor position is not in extras
+ return SwOutlineNodes::npos;
+ }
+ return nPos;
+ }
+ }
+ return SwOutlineNodes::npos; // no more left
+}
+
+void SwCursorShell::MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineNodes::size_type nEndPos,
+ bool bWithChildren , bool bKillPams)
+{
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ if( rOutlNds.empty() )
+ return;
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+
+ if( nSttPos > nEndPos ) // parameters switched?
+ {
+ OSL_ENSURE( false, "Start > End for array access" );
+ std::swap(nSttPos, nEndPos);
+ }
+
+ SwNode* pSttNd = rOutlNds[ nSttPos ];
+ SwNode* pEndNd = rOutlNds[ nEndPos ];
+
+ if( bWithChildren )
+ {
+ const int nLevel = pEndNd->GetTextNode()->GetAttrOutlineLevel()-1;
+ for( ++nEndPos; nEndPos < rOutlNds.size(); ++nEndPos )
+ {
+ pEndNd = rOutlNds[ nEndPos ];
+ const int nNxtLevel = pEndNd->GetTextNode()->GetAttrOutlineLevel()-1;
+ if( nNxtLevel <= nLevel )
+ break; // EndPos is now on the next one
+ }
+ }
+ // if without children then set onto next one
+ else if( ++nEndPos < rOutlNds.size() )
+ pEndNd = rOutlNds[ nEndPos ];
+
+ if( nEndPos == rOutlNds.size() ) // no end found
+ pEndNd = &rNds.GetEndOfContent();
+
+ if( bKillPams )
+ KillPams();
+
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ // set end to the end of the previous content node
+ m_pCurrentCursor->GetPoint()->nNode = *pSttNd;
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pSttNd->GetContentNode(), 0 );
+ m_pCurrentCursor->SetMark();
+ m_pCurrentCursor->GetPoint()->nNode = *pEndNd;
+ m_pCurrentCursor->Move( fnMoveBackward, GoInNode ); // end of predecessor
+
+ // and everything is already selected
+ bool bRet = !m_pCurrentCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+}
+
+/// jump to reference marker
+bool SwCursorShell::GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType,
+ sal_uInt16 nSeqNo )
+{
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ sal_Int32 nPos = -1;
+ SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark,
+ nSubType, nSeqNo, &nPos, nullptr, GetLayout());
+ if( pTextNd && pTextNd->GetNodes().IsDocNodes() )
+ {
+ m_pCurrentCursor->GetPoint()->nNode = *pTextNd;
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pTextNd, nPos );
+
+ if( !m_pCurrentCursor->IsSelOvr() )
+ {
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SwCursorShell::IsPageAtPos( const Point &rPt ) const
+{
+ if( GetLayout() )
+ return nullptr != GetLayout()->GetPageAtPos( rPt );
+ return false;
+}
+
+bool SwCursorShell::GetContentAtPos( const Point& rPt,
+ SwContentAtPos& rContentAtPos,
+ bool bSetCursor,
+ SwRect* pFieldRect )
+{
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ if( !IsTableMode() )
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *m_pCurrentCursor->GetPoint() );
+
+ SwTextNode* pTextNd;
+ SwCursorMoveState aTmpState;
+ aTmpState.m_bFieldInfo = true;
+ aTmpState.m_bExactOnly = !( IsAttrAtPos::Outline & rContentAtPos.eContentAtPos );
+ aTmpState.m_bContentCheck = bool(IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos);
+ aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwSpecialPos aSpecialPos;
+ aTmpState.m_pSpecialPos = ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos ) ?
+ &aSpecialPos : nullptr;
+
+ const bool bCursorFoundExact = GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState );
+ pTextNd = aPos.nNode.GetNode().GetTextNode();
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ if( pTextNd
+ && IsAttrAtPos::Outline & rContentAtPos.eContentAtPos
+ && !rNds.GetOutLineNds().empty() )
+ {
+ // only for nodes in outline nodes
+ SwOutlineNodes::size_type nPos;
+ if(rNds.GetOutLineNds().Seek_Entry(pTextNd, &nPos))
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::Outline;
+ rContentAtPos.sStr = sw::GetExpandTextMerged(GetLayout(), *pTextNd, true, false, ExpandMode::ExpandFootnote);
+ rContentAtPos.aFnd.pNode = pTextNd;
+ bRet = true;
+ }
+ }
+ else if ( IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos
+ && bCursorFoundExact )
+ {
+ bRet = true;
+ }
+ else if( pTextNd
+ && IsAttrAtPos::NumLabel & rContentAtPos.eContentAtPos)
+ {
+ bRet = aTmpState.m_bInNumPortion;
+ rContentAtPos.aFnd.pNode = sw::GetParaPropsNode(*GetLayout(), aPos.nNode);
+
+ Size aSizeLogic(aTmpState.m_nInNumPortionOffset, 0);
+ Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic);
+ rContentAtPos.nDist = aSizePixel.Width();
+ }
+ else if( bCursorFoundExact && pTextNd )
+ {
+ SwContentFrame *pFrame(nullptr);
+ if( !aTmpState.m_bPosCorr )
+ {
+ SwTextAttr* pTextAttr;
+ if ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos
+ && !aTmpState.m_bFootnoteNoInfo )
+ {
+ const SwWrongList* pSmartTagList = pTextNd->GetSmartTags();
+ sal_Int32 nCurrent = aPos.nContent.GetIndex();
+ const sal_Int32 nBegin = nCurrent;
+ sal_Int32 nLen = 1;
+
+ if (pSmartTagList && pSmartTagList->InWrongWord(nCurrent, nLen) && !pTextNd->IsSymbolAt(nBegin))
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ nCurrent = aTmpState.m_pSpecialPos->nCharOfst;
+
+ if ( pSubList->InWrongWord( nCurrent, nLen ) )
+ bRet = true;
+ }
+ else
+ bRet = true;
+
+ if( bRet && bSetCursor )
+ {
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ m_pCurrentCursor->DeleteMark();
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle) )
+ bRet = false;
+ else
+ UpdateCursor();
+ }
+ if( bRet )
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::SmartTag;
+
+ std::pair<Point, bool> tmp(aPt, true);
+ if (pFieldRect)
+ {
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState );
+ }
+ }
+ }
+ }
+
+ if ( !bRet
+ && ( IsAttrAtPos::Field | IsAttrAtPos::ClickField ) & rContentAtPos.eContentAtPos
+ && !aTmpState.m_bFootnoteNoInfo )
+ {
+ pTextAttr = pTextNd->GetFieldTextAttrAt( aPos.nContent.GetIndex() );
+ const SwField* pField = pTextAttr != nullptr
+ ? pTextAttr->GetFormatField().GetField()
+ : nullptr;
+ if ( IsAttrAtPos::ClickField & rContentAtPos.eContentAtPos
+ && pField && !pField->HasClickHdl() )
+ {
+ pField = nullptr;
+ }
+
+ if ( pField )
+ {
+ if (pFieldRect)
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ {
+ //tdf#116397 now that we looking for the bounds of the field drop the SmartTag
+ //index within field setting so we don't the bounds of the char within the field
+ SwSpecialPos* pSpecialPos = aTmpState.m_pSpecialPos;
+ aTmpState.m_pSpecialPos = nullptr;
+ pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState );
+ aTmpState.m_pSpecialPos = pSpecialPos;
+ }
+ }
+
+ if( bSetCursor )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ m_pCurrentCursor->DeleteMark();
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( m_pCurrentCursor->IsSelOvr() )
+ {
+ // allow click fields in protected sections
+ // only placeholder is not possible
+ if( IsAttrAtPos::Field & rContentAtPos.eContentAtPos
+ || SwFieldIds::JumpEdit == pField->Which() )
+ pField = nullptr;
+ }
+ else
+ UpdateCursor();
+ }
+ else if( SwFieldIds::Table == pField->Which() &&
+ static_cast<const SwTableField*>(pField)->IsIntrnlName() )
+ {
+ // create from internal (for CORE) the external
+ // (for UI) formula
+ const SwTableNode* pTableNd = pTextNd->FindTableNode();
+ if( pTableNd ) // is in a table
+ const_cast<SwTableField*>(static_cast<const SwTableField*>(pField))->PtrToBoxNm( &pTableNd->GetTable() );
+ }
+ }
+
+ if( pField )
+ {
+ rContentAtPos.aFnd.pField = pField;
+ rContentAtPos.pFndTextAttr = pTextAttr;
+ rContentAtPos.eContentAtPos = IsAttrAtPos::Field;
+ bRet = true;
+ }
+ }
+
+ if( !bRet && IsAttrAtPos::FormControl & rContentAtPos.eContentAtPos )
+ {
+ IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
+ sw::mark::IFieldmark* pFieldBookmark = pMarksAccess->getFieldmarkFor( aPos );
+ if (bCursorFoundExact && pFieldBookmark)
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::FormControl;
+ rContentAtPos.aFnd.pFieldmark = pFieldBookmark;
+ bRet=true;
+ }
+ }
+
+ if (!bRet && rContentAtPos.eContentAtPos & IsAttrAtPos::ContentControl)
+ {
+ SwTextAttr* pAttr = pTextNd->GetTextAttrAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT);
+ if (pAttr)
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::ContentControl;
+ rContentAtPos.pFndTextAttr = pAttr;
+ bRet = true;
+ }
+ }
+
+ if( !bRet && IsAttrAtPos::Ftn & rContentAtPos.eContentAtPos )
+ {
+ if( aTmpState.m_bFootnoteNoInfo )
+ {
+ // over the footnote's char
+ bRet = true;
+ if( bSetCursor )
+ {
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( !GotoFootnoteAnchor() )
+ bRet = false;
+ }
+ if( bRet )
+ rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn;
+ }
+ else if ( nullptr != ( pTextAttr = pTextNd->GetTextAttrForCharAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_FTN )) )
+ {
+ bRet = true;
+ if( bSetCursor )
+ {
+ if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this))
+ pWrtSh->addCurrentPosition();
+
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ m_pCurrentCursor->GetPoint()->nNode = *static_cast<SwTextFootnote*>(pTextAttr)->GetStartNode();
+ SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection(
+ &m_pCurrentCursor->GetPoint()->nNode,
+ true, !IsReadOnlyAvailable() );
+
+ if( pCNd )
+ {
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, 0 );
+ if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
+ SwCursorSelOverFlags::Toggle ))
+ bRet = false;
+ else
+ UpdateCursor();
+ }
+ else
+ bRet = false;
+ }
+
+ if( bRet )
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn;
+ rContentAtPos.pFndTextAttr = pTextAttr;
+ rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr();
+
+ if (pFieldRect)
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState );
+ }
+ }
+ }
+ }
+
+ if( !bRet
+ && ( IsAttrAtPos::ToxMark | IsAttrAtPos::RefMark ) & rContentAtPos.eContentAtPos
+ && !aTmpState.m_bFootnoteNoInfo )
+ {
+ pTextAttr = nullptr;
+ if( IsAttrAtPos::ToxMark & rContentAtPos.eContentAtPos )
+ {
+ std::vector<SwTextAttr *> const marks(
+ pTextNd->GetTextAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_TOXMARK));
+ if (!marks.empty())
+ { // hmm... can only return 1 here
+ pTextAttr = *marks.begin();
+ }
+ }
+
+ if( !pTextAttr &&
+ IsAttrAtPos::RefMark & rContentAtPos.eContentAtPos )
+ {
+ std::vector<SwTextAttr *> const marks(
+ pTextNd->GetTextAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_REFMARK));
+ if (!marks.empty())
+ { // hmm... can only return 1 here
+ pTextAttr = *marks.begin();
+ }
+ }
+
+ if( pTextAttr )
+ {
+ bRet = true;
+ if( bSetCursor )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ m_pCurrentCursor->DeleteMark();
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle ) )
+ bRet = false;
+ else
+ UpdateCursor();
+ }
+
+ if( bRet )
+ {
+ const sal_Int32* pEnd = pTextAttr->GetEnd();
+ if( pEnd )
+ rContentAtPos.sStr =
+ pTextNd->GetExpandText(GetLayout(), pTextAttr->GetStart(), *pEnd - pTextAttr->GetStart());
+ else if( RES_TXTATR_TOXMARK == pTextAttr->Which())
+ rContentAtPos.sStr =
+ pTextAttr->GetTOXMark().GetAlternativeText();
+
+ rContentAtPos.eContentAtPos =
+ RES_TXTATR_TOXMARK == pTextAttr->Which()
+ ? IsAttrAtPos::ToxMark
+ : IsAttrAtPos::RefMark;
+ rContentAtPos.pFndTextAttr = pTextAttr;
+ rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr();
+
+ std::pair<Point, bool> tmp(aPt, true);
+ if (pFieldRect)
+ {
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState );
+ }
+ }
+ }
+ }
+
+ if ( !bRet
+ && IsAttrAtPos::InetAttr & rContentAtPos.eContentAtPos
+ && !aTmpState.m_bFootnoteNoInfo )
+ {
+ sal_Int32 index = aPos.nContent.GetIndex();
+ pTextAttr = pTextNd->GetTextAttrAt(index, RES_TXTATR_INETFMT);
+
+ if(!pTextAttr && index > 0)
+ pTextAttr = pTextNd->GetTextAttrAt(index - 1, RES_TXTATR_INETFMT);
+ // "detect" only INetAttrs with URLs
+ if( pTextAttr && !pTextAttr->GetINetFormat().GetValue().isEmpty() )
+ {
+ bRet = true;
+ if( bSetCursor )
+ {
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ m_pCurrentCursor->DeleteMark();
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
+ SwCursorSelOverFlags::Toggle) )
+ bRet = false;
+ else
+ UpdateCursor();
+ }
+ if( bRet )
+ {
+ const sal_Int32 nSt = pTextAttr->GetStart();
+ const sal_Int32 nEnd = *pTextAttr->End();
+
+ rContentAtPos.sStr = pTextNd->GetExpandText(GetLayout(), nSt, nEnd-nSt);
+
+ rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr();
+ rContentAtPos.eContentAtPos = IsAttrAtPos::InetAttr;
+ rContentAtPos.pFndTextAttr = pTextAttr;
+
+ if (pFieldRect)
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ {
+ //get bounding box of range
+ SwRect aStart;
+ SwPosition aStartPos(*pTextNd, nSt);
+ pFrame->GetCharRect(aStart, aStartPos, &aTmpState);
+ SwRect aEnd;
+ SwPosition aEndPos(*pTextNd, nEnd);
+ pFrame->GetCharRect(aEnd, aEndPos, &aTmpState);
+ if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom())
+ {
+ aStart.Left(pFrame->getFrameArea().Left());
+ aEnd.Right(pFrame->getFrameArea().Right());
+ }
+ *pFieldRect = aStart.Union(aEnd);
+ }
+ }
+ }
+ }
+ }
+
+ if( !bRet && IsAttrAtPos::Redline & rContentAtPos.eContentAtPos )
+ {
+ const SwRangeRedline* pRedl = GetDoc()->getIDocumentRedlineAccess().GetRedline(aPos, nullptr);
+
+ if( pRedl )
+ {
+ rContentAtPos.aFnd.pRedl = pRedl;
+ rContentAtPos.eContentAtPos = IsAttrAtPos::Redline;
+ rContentAtPos.pFndTextAttr = nullptr;
+ bRet = true;
+
+ if (pFieldRect)
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if( pFrame )
+ {
+ // not sure if this should be limited to one
+ // paragraph, or mark the entire redline; let's
+ // leave it limited to one for now...
+ sal_Int32 nStart;
+ sal_Int32 nEnd;
+ pRedl->CalcStartEnd(pTextNd->GetIndex(), nStart, nEnd);
+ if (nStart == COMPLETE_STRING)
+ {
+ // consistency: found pRedl, so there must be
+ // something in pTextNd
+ assert(nEnd != COMPLETE_STRING);
+ nStart = 0;
+ }
+ if (nEnd == COMPLETE_STRING)
+ {
+ nEnd = pTextNd->Len();
+ }
+ //get bounding box of range
+ SwRect aStart;
+ pFrame->GetCharRect(aStart, SwPosition(*pTextNd, nStart), &aTmpState);
+ SwRect aEnd;
+ pFrame->GetCharRect(aEnd, SwPosition(*pTextNd, nEnd), &aTmpState);
+ if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom())
+ {
+ aStart.Left(pFrame->getFrameArea().Left());
+ aEnd.Right(pFrame->getFrameArea().Right());
+ }
+ *pFieldRect = aStart.Union(aEnd);
+ }
+ }
+ }
+ }
+ }
+
+ if( !bRet && ( IsAttrAtPos::TableRedline & rContentAtPos.eContentAtPos ) )
+ {
+ const SwTableNode* pTableNd;
+ const SwTableBox* pBox;
+ const SwTableLine* pTableLine;
+ const SwStartNode* pSttNd = pTextNd->FindTableBoxStartNode();
+ if( pSttNd && nullptr != ( pTableNd = pTextNd->FindTableNode()) &&
+ nullptr != ( pBox = pTableNd->GetTable().GetTableBox(
+ pSttNd->GetIndex() )) &&
+ nullptr != ( pTableLine = pBox->GetUpper() ) &&
+ RedlineType::None != pTableLine->GetRedlineType() )
+ {
+ SwRedlineTable::size_type nPos = 0;
+ nPos = pTableLine->UpdateTextChangesOnly(nPos);
+ if ( nPos != SwRedlineTable::npos )
+ {
+ rContentAtPos.aFnd.pRedl = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable()[nPos];
+ rContentAtPos.eContentAtPos = IsAttrAtPos::TableRedline;
+ bRet = true;
+ }
+
+ }
+ }
+
+ if( !bRet
+ && ( IsAttrAtPos::TableBoxFml & rContentAtPos.eContentAtPos
+#ifdef DBG_UTIL
+ || IsAttrAtPos::TableBoxValue & rContentAtPos.eContentAtPos
+#endif
+ ) )
+ {
+ const SwTableNode* pTableNd;
+ const SwTableBox* pBox;
+ const SwStartNode* pSttNd = pTextNd->FindTableBoxStartNode();
+ const SwTableBoxFormula* pItem;
+#ifdef DBG_UTIL
+ const SwTableBoxValue* pItem2 = nullptr;
+#endif
+ if( pSttNd && nullptr != ( pTableNd = pTextNd->FindTableNode()) &&
+ nullptr != ( pBox = pTableNd->GetTable().GetTableBox(
+ pSttNd->GetIndex() )) &&
+#ifdef DBG_UTIL
+ ( (pItem = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMULA, false )) ||
+ (pItem2 = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_VALUE, false )) )
+#else
+ (pItem = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMULA, false ))
+#endif
+ )
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ SwFrame* pF = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if( pF )
+ {
+ // then the CellFrame
+ pFrame = static_cast<SwContentFrame*>(pF);
+ while( pF && !pF->IsCellFrame() )
+ pF = pF->GetUpper();
+ }
+
+ if( aTmpState.m_bPosCorr )
+ {
+ if( pF && !pF->getFrameArea().Contains( aPt ))
+ pF = nullptr;
+ }
+ else if( !pF )
+ pF = pFrame;
+
+ if( pF ) // only then it is valid
+ {
+ // create from internal (for CORE) the external
+ // (for UI) formula
+ rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxFml;
+#ifdef DBG_UTIL
+ if( pItem2 )
+ rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxValue;
+ else
+#endif
+ const_cast<SwTableBoxFormula&>(*pItem).PtrToBoxNm( &pTableNd->GetTable() );
+
+ bRet = true;
+ if( bSetCursor )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+ *m_pCurrentCursor->GetPoint() = aPos;
+ if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
+ SwCursorSelOverFlags::Toggle) )
+ bRet = false;
+ else
+ UpdateCursor();
+ }
+
+ if( bRet )
+ {
+ if( pFieldRect )
+ {
+ *pFieldRect = pF->getFramePrintArea();
+ *pFieldRect += pF->getFrameArea().Pos();
+ }
+ rContentAtPos.pFndTextAttr = nullptr;
+ rContentAtPos.aFnd.pAttr = pItem;
+ }
+ }
+ }
+ }
+
+#ifdef DBG_UTIL
+ if( !bRet && IsAttrAtPos::CurrAttrs & rContentAtPos.eContentAtPos )
+ {
+ const sal_Int32 n = aPos.nContent.GetIndex();
+ SfxItemSetFixed<POOLATTR_BEGIN, POOLATTR_END - 1> aSet( GetDoc()->GetAttrPool() );
+ if( pTextNd->GetpSwpHints() )
+ {
+ for( size_t i = 0; i < pTextNd->GetSwpHints().Count(); ++i )
+ {
+ const SwTextAttr* pHt = pTextNd->GetSwpHints().Get(i);
+ const sal_Int32 nAttrStart = pHt->GetStart();
+ if( nAttrStart > n ) // over the section
+ break;
+
+ if( nullptr != pHt->End() && (
+ ( nAttrStart < n &&
+ ( pHt->DontExpand() ? n < *pHt->End()
+ : n <= *pHt->End() )) ||
+ ( n == nAttrStart &&
+ ( nAttrStart == *pHt->End() || !n ))) )
+ {
+ aSet.Put( pHt->GetAttr() );
+ }
+ }
+ if( pTextNd->HasSwAttrSet() &&
+ pTextNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemSet aFormatSet( pTextNd->GetSwAttrSet() );
+ // remove all from format set that are also in TextSet
+ aFormatSet.Differentiate( aSet );
+ // now merge all together
+ aSet.Put( aFormatSet );
+ }
+ }
+ else
+ pTextNd->SwContentNode::GetAttr( aSet );
+
+ rContentAtPos.sStr = "Pos: (";
+ rContentAtPos.sStr += OUString::number( sal_Int32(aPos.nNode.GetIndex()));
+ rContentAtPos.sStr += ":";
+ rContentAtPos.sStr += OUString::number( aPos.nContent.GetIndex());
+ rContentAtPos.sStr += ")";
+ rContentAtPos.sStr += "\nParagraph Style: ";
+ rContentAtPos.sStr += pTextNd->GetFormatColl()->GetName();
+ if( pTextNd->GetCondFormatColl() )
+ {
+ rContentAtPos.sStr += "\nConditional Style: " + pTextNd->GetCondFormatColl()->GetName();
+ }
+
+ if( aSet.Count() )
+ {
+ OUStringBuffer sAttrs;
+ SfxItemIter aIter( aSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const IntlWrapper aInt(SvtSysLocale().GetUILanguageTag());
+ do
+ {
+ if( !IsInvalidItem( pItem ))
+ {
+ OUString aStr;
+ GetDoc()->GetAttrPool().GetPresentation(*pItem,
+ MapUnit::MapCM, aStr, aInt);
+ if (!sAttrs.isEmpty())
+ sAttrs.append(", ");
+ sAttrs.append(aStr);
+ }
+ pItem = aIter.NextItem();
+ } while (pItem);
+ if (!sAttrs.isEmpty())
+ {
+ if( !rContentAtPos.sStr.isEmpty() )
+ rContentAtPos.sStr += "\n";
+ rContentAtPos.sStr += "Attr: " + sAttrs.makeStringAndClear();
+ }
+ }
+ bRet = true;
+ rContentAtPos.eContentAtPos = IsAttrAtPos::CurrAttrs;
+ }
+#endif
+ }
+ }
+
+ if( !bRet )
+ {
+ rContentAtPos.eContentAtPos = IsAttrAtPos::NONE;
+ rContentAtPos.aFnd.pField = nullptr;
+ }
+ return bRet;
+}
+
+// #i90516#
+const SwPostItField* SwCursorShell::GetPostItFieldAtCursor() const
+{
+ const SwPostItField* pPostItField = nullptr;
+
+ if ( !IsTableMode() )
+ {
+ const SwPosition* pCursorPos = GetCursor_()->GetPoint();
+ const SwTextNode* pTextNd = pCursorPos->nNode.GetNode().GetTextNode();
+ if ( pTextNd )
+ {
+ SwTextAttr* pTextAttr = pTextNd->GetFieldTextAttrAt( pCursorPos->nContent.GetIndex() );
+ const SwField* pField = pTextAttr != nullptr ? pTextAttr->GetFormatField().GetField() : nullptr;
+ if ( pField && pField->Which()== SwFieldIds::Postit )
+ {
+ pPostItField = static_cast<const SwPostItField*>(pField);
+ }
+ }
+ }
+
+ return pPostItField;
+}
+
+/// is the node in a protected section?
+bool SwContentAtPos::IsInProtectSect() const
+{
+ const SwTextNode* pNd = nullptr;
+ if( pFndTextAttr )
+ {
+ switch( eContentAtPos )
+ {
+ case IsAttrAtPos::Field:
+ case IsAttrAtPos::ClickField:
+ pNd = static_txtattr_cast<SwTextField const*>(pFndTextAttr)->GetpTextNode();
+ break;
+
+ case IsAttrAtPos::Ftn:
+ pNd = &static_cast<const SwTextFootnote*>(pFndTextAttr)->GetTextNode();
+ break;
+
+ case IsAttrAtPos::InetAttr:
+ pNd = static_txtattr_cast<SwTextINetFormat const*>(pFndTextAttr)->GetpTextNode();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if( !pNd )
+ return false;
+ if( pNd->IsInProtectSect() )
+ return true;
+
+ const SwContentFrame* pFrame = pNd->getLayoutFrame(pNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, nullptr);
+ return pFrame && pFrame->IsProtected() ;
+}
+
+bool SwContentAtPos::IsInRTLText()const
+{
+ bool bRet = false;
+ const SwTextNode* pNd = nullptr;
+ if (pFndTextAttr && (eContentAtPos == IsAttrAtPos::Ftn))
+ {
+ const SwTextFootnote* pTextFootnote = static_cast<const SwTextFootnote*>(pFndTextAttr);
+ if(pTextFootnote->GetStartNode())
+ {
+ SwStartNode* pSttNd = pTextFootnote->GetStartNode()->GetNode().GetStartNode();
+ SwPaM aTemp( *pSttNd );
+ aTemp.Move(fnMoveForward, GoInNode);
+ SwContentNode* pContentNode = aTemp.GetContentNode();
+ if(pContentNode && pContentNode->IsTextNode())
+ pNd = pContentNode->GetTextNode();
+ }
+ }
+ if(pNd)
+ {
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pNd);
+ SwTextFrame* pTmpFrame = aIter.First();
+ while( pTmpFrame )
+ {
+ if ( !pTmpFrame->IsFollow())
+ {
+ bRet = pTmpFrame->IsRightToLeft();
+ break;
+ }
+ pTmpFrame = aIter.Next();
+ }
+ }
+ return bRet;
+}
+
+bool SwCursorShell::SelectTextModel( const sal_Int32 nStart,
+ const sal_Int32 nEnd )
+{
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ SwCallLink aLk( *this );
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+ m_pCurrentCursor->DeleteMark();
+ rPos.nContent = nStart;
+ m_pCurrentCursor->SetMark();
+ rPos.nContent = nEnd;
+
+ if( !m_pCurrentCursor->IsSelOvr() )
+ {
+ UpdateCursor();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+TextFrameIndex SwCursorShell::GetCursorPointAsViewIndex() const
+{
+ SwPosition const*const pPos(GetCursor()->GetPoint());
+ SwTextNode const*const pTextNode(pPos->nNode.GetNode().GetTextNode());
+ assert(pTextNode);
+ SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTextNode->getLayoutFrame(GetLayout())));
+ assert(pFrame);
+ return pFrame->MapModelToViewPos(*pPos);
+}
+
+bool SwCursorShell::SelectTextView(TextFrameIndex const nStart,
+ TextFrameIndex const nEnd)
+{
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ SwCallLink aLk( *this );
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+ m_pCurrentCursor->DeleteMark();
+ // indexes must correspond to cursor point!
+ SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode()->getLayoutFrame(GetLayout())));
+ assert(pFrame);
+ rPos = pFrame->MapViewToModelPos(nStart);
+ m_pCurrentCursor->SetMark();
+ rPos = pFrame->MapViewToModelPos(nEnd);
+
+ if (!m_pCurrentCursor->IsSelOvr())
+ {
+ UpdateCursor();
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool SwCursorShell::SelectTextAttr( sal_uInt16 nWhich,
+ bool bExpand,
+ const SwTextAttr* pTextAttr )
+{
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ if( !IsTableMode() )
+ {
+ if( !pTextAttr )
+ {
+ SwPosition& rPos = *m_pCurrentCursor->GetPoint();
+ SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode();
+ pTextAttr = pTextNd
+ ? pTextNd->GetTextAttrAt(rPos.nContent.GetIndex(),
+ nWhich,
+ bExpand ? SwTextNode::EXPAND : SwTextNode::DEFAULT)
+ : nullptr;
+ }
+
+ if( pTextAttr )
+ {
+ const sal_Int32* pEnd = pTextAttr->End();
+ bRet = SelectTextModel(pTextAttr->GetStart(), (pEnd ? *pEnd : pTextAttr->GetStart() + 1));
+ }
+ }
+ return bRet;
+}
+
+bool SwCursorShell::GotoINetAttr( const SwTextINetFormat& rAttr )
+{
+ bool bRet = false;
+ if( rAttr.GetpTextNode() )
+ {
+ SwCursor* pCursor = getShellCursor( true );
+
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *pCursor );
+
+ pCursor->GetPoint()->nNode = *rAttr.GetpTextNode();
+ pCursor->GetPoint()->nContent.Assign( const_cast<SwTextNode*>(rAttr.GetpTextNode()),
+ rAttr.GetStart() );
+ bRet = !pCursor->IsSelOvr();
+ if( bRet )
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ }
+ return bRet;
+}
+
+const SwFormatINetFormat* SwCursorShell::FindINetAttr( std::u16string_view rName ) const
+{
+ return mxDoc->FindINetAttr( rName );
+}
+
+bool SwCursorShell::GetShadowCursorPos( const Point& rPt, SwFillMode eFillMode,
+ SwRect& rRect, sal_Int16& rOrient )
+{
+
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ if (!IsTableMode() && !HasSelection()
+ && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *m_pCurrentCursor->GetPoint() );
+
+ SwFillCursorPos aFPos( eFillMode );
+ SwCursorMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) &&
+ !aPos.nNode.GetNode().IsProtect())
+ {
+ // start position in protected section?
+ rRect = aFPos.aCursor;
+ rOrient = aFPos.eOrient;
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+bool SwCursorShell::SetShadowCursorPos( const Point& rPt, SwFillMode eFillMode )
+{
+ CurrShell aCurr( this );
+ bool bRet = false;
+
+ if (!IsTableMode() && !HasSelection()
+ && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *m_pCurrentCursor->GetPoint() );
+
+ SwFillCursorPos aFPos( eFillMode );
+ SwCursorMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) )
+ {
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ StartAction();
+
+ SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode();
+ SwUndoId nUndoId = SwUndoId::INS_FROM_SHADOWCRSR;
+ // If only the paragraph attributes "Adjust" or "LRSpace" are set,
+ // then the following should not delete those again.
+ if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt &&
+ ( SwFillMode::Indent == aFPos.eMode ||
+ ( text::HoriOrientation::NONE != aFPos.eOrient &&
+ 0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) &&
+ pCNd && pCNd->Len() )
+ nUndoId = SwUndoId::EMPTY;
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( nUndoId, nullptr );
+
+ SwTextFormatColl* pNextFormat = nullptr;
+ SwTextNode* pTNd = pCNd ? pCNd->GetTextNode() : nullptr;
+ if( pTNd )
+ pNextFormat = &pTNd->GetTextColl()->GetNextTextFormatColl();
+
+ const SwSectionNode* pSectNd = pCNd ? pCNd->FindSectionNode() : nullptr;
+ if( pSectNd && aFPos.nParaCnt )
+ {
+ SwNodeIndex aEnd( aPos.nNode, 1 );
+ while( aEnd.GetNode().IsEndNode() &&
+ &aEnd.GetNode() !=
+ pSectNd->EndOfSectionNode() )
+ ++aEnd;
+
+ if( aEnd.GetNode().IsEndNode() &&
+ pCNd->Len() == aPos.nContent.GetIndex() )
+ aPos.nNode = *pSectNd->EndOfSectionNode();
+ }
+
+ for( sal_uInt16 n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n )
+ {
+ GetDoc()->getIDocumentContentOperations().AppendTextNode( aPos );
+ if( !n && pNextFormat )
+ {
+ *m_pCurrentCursor->GetPoint() = aPos;
+ GetDoc()->SetTextFormatColl( *m_pCurrentCursor, pNextFormat, false );
+ }
+ if( n < aFPos.nColumnCnt )
+ {
+ *m_pCurrentCursor->GetPoint() = aPos;
+ GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor,
+ SvxFormatBreakItem( SvxBreak::ColumnBefore, RES_BREAK ) );
+ }
+ }
+
+ *m_pCurrentCursor->GetPoint() = aPos;
+ switch( aFPos.eMode )
+ {
+ case SwFillMode::Indent:
+ if( nullptr != (pCNd = aPos.nNode.GetNode().GetContentNode() ))
+ {
+ SfxItemSetFixed<
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ RES_LR_SPACE, RES_LR_SPACE> aSet( GetDoc()->GetAttrPool() );
+ SvxLRSpaceItem aLR(pCNd->GetAttr(RES_LR_SPACE));
+ aLR.SetTextLeft( aFPos.nTabCnt );
+ aLR.SetTextFirstLineOffset( 0 );
+ aSet.Put( aLR );
+
+ const SvxAdjustItem& rAdj = pCNd->GetAttr(RES_PARATR_ADJUST);
+ if( SvxAdjust::Left != rAdj.GetAdjust() )
+ aSet.Put( SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST ) );
+
+ GetDoc()->getIDocumentContentOperations().InsertItemSet( *m_pCurrentCursor, aSet );
+ }
+ else {
+ OSL_ENSURE( false, "No ContentNode" );
+ }
+ break;
+
+ case SwFillMode::Tab:
+ case SwFillMode::TabSpace:
+ case SwFillMode::Space:
+ {
+ OUStringBuffer sInsert;
+ if (aFPos.eMode == SwFillMode::Space)
+ {
+ comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceOnlyCnt, ' ');
+ }
+ else
+ {
+ if (aFPos.nTabCnt)
+ comphelper::string::padToLength(sInsert, aFPos.nTabCnt, '\t');
+ if (aFPos.nSpaceCnt)
+ comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceCnt, ' ');
+ }
+ if (!sInsert.isEmpty())
+ GetDoc()->getIDocumentContentOperations().InsertString( *m_pCurrentCursor, sInsert.makeStringAndClear());
+ }
+ [[fallthrough]]; // still need to set orientation
+ case SwFillMode::Margin:
+ if( text::HoriOrientation::NONE != aFPos.eOrient )
+ {
+ SvxAdjustItem aAdj( SvxAdjust::Left, RES_PARATR_ADJUST );
+ switch( aFPos.eOrient )
+ {
+ case text::HoriOrientation::CENTER:
+ aAdj.SetAdjust( SvxAdjust::Center );
+ break;
+ case text::HoriOrientation::RIGHT:
+ aAdj.SetAdjust( SvxAdjust::Right );
+ break;
+ default:
+ break;
+ }
+ GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor, aAdj );
+ }
+ break;
+ }
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( nUndoId, nullptr );
+ EndAction();
+
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+const SwRangeRedline* SwCursorShell::SelNextRedline()
+{
+ const SwRangeRedline* pFnd = nullptr;
+ if( !IsTableMode() )
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ // ensure point is at the end so alternating SelNext/SelPrev works
+ NormalizePam(false);
+ pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor );
+
+ // at the end of the document, go to the start of the document, and try again
+ if ( !pFnd )
+ {
+ GetDoc()->GetDocShell()->GetWrtShell()->StartOfSection();
+ pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor );
+ }
+
+ if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() )
+ UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ else
+ pFnd = nullptr;
+ }
+ return pFnd;
+}
+
+const SwRangeRedline* SwCursorShell::SelPrevRedline()
+{
+ const SwRangeRedline* pFnd = nullptr;
+ if( !IsTableMode() )
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ // ensure point is at the start so alternating SelNext/SelPrev works
+ NormalizePam(true);
+ pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor );
+
+ // at the start of the document, go to the end of the document, and try again
+ if ( !pFnd )
+ {
+ GetDoc()->GetDocShell()->GetWrtShell()->EndOfSection();
+ pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor );
+ }
+
+ if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() )
+ UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ else
+ pFnd = nullptr;
+ }
+ return pFnd;
+}
+
+const SwRangeRedline* SwCursorShell::GotoRedline_( SwRedlineTable::size_type nArrPos, bool bSelect )
+{
+ const SwRangeRedline* pFnd = nullptr;
+ SwCallLink aLk( *this ); // watch Cursor-Moves
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ pFnd = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable()[ nArrPos ];
+ if( pFnd )
+ {
+ *m_pCurrentCursor->GetPoint() = *pFnd->Start();
+
+ SwNodeIndex* pIdx = &m_pCurrentCursor->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsContentNode() )
+ {
+ SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( pIdx,
+ true, IsReadOnlyAvailable() );
+ if( pCNd )
+ {
+ if( *pIdx <= pFnd->End()->nNode )
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = nullptr;
+ }
+ }
+
+ if( pFnd && bSelect )
+ {
+ m_pCurrentCursor->SetMark();
+ if( RedlineType::FmtColl == pFnd->GetType() )
+ {
+ SwContentNode* pCNd = pIdx->GetNode().GetContentNode();
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ m_pCurrentCursor->GetMark()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ *m_pCurrentCursor->GetPoint() = *pFnd->End();
+
+ pIdx = &m_pCurrentCursor->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsContentNode() )
+ {
+ SwContentNode* pCNd = SwNodes::GoPrevSection( pIdx,
+ true, IsReadOnlyAvailable() );
+ if( pCNd )
+ {
+ if( *pIdx >= m_pCurrentCursor->GetMark()->nNode )
+ m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = nullptr;
+ }
+ }
+ }
+
+ if( !pFnd )
+ {
+ m_pCurrentCursor->DeleteMark();
+ m_pCurrentCursor->RestoreSavePos();
+ }
+ else if( bSelect && *m_pCurrentCursor->GetMark() == *m_pCurrentCursor->GetPoint() )
+ m_pCurrentCursor->DeleteMark();
+
+ if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() )
+ UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE
+ | SwCursorShell::READONLY );
+ else
+ {
+ pFnd = nullptr;
+ if( bSelect )
+ m_pCurrentCursor->DeleteMark();
+ }
+ }
+ return pFnd;
+}
+
+const SwRangeRedline* SwCursorShell::GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect )
+{
+ const SwRangeRedline* pFnd = nullptr;
+ if( !IsTableMode() )
+ {
+ CurrShell aCurr( this );
+
+ const SwRedlineTable& rTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
+ const SwRangeRedline* pTmp = rTable[ nArrPos ];
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+ if( nSeqNo && bSelect )
+ {
+ bool bCheck = false;
+ int nLoopCnt = 2;
+ SwRedlineTable::size_type nArrSavPos = nArrPos;
+
+ do {
+ pTmp = GotoRedline_( nArrPos, true );
+
+ if( !pFnd )
+ pFnd = pTmp;
+
+ if( pTmp && bCheck )
+ {
+ // Check for overlaps. These can happen when FormatColl-
+ // Redlines were stretched over a whole paragraph
+ SwPaM* pCur = m_pCurrentCursor;
+ SwPaM* pNextPam = pCur->GetNext();
+ SwPosition* pCStt = pCur->Start(), *pCEnd = pCur->End();
+ while( pCur != pNextPam )
+ {
+ const SwPosition *pNStt = pNextPam->Start(),
+ *pNEnd = pNextPam->End();
+
+ bool bDel = true;
+ switch( ::ComparePosition( *pCStt, *pCEnd,
+ *pNStt, *pNEnd ))
+ {
+ case SwComparePosition::Inside: // Pos1 is completely in Pos2
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ *pCEnd = *pNEnd;
+ break;
+
+ case SwComparePosition::Outside: // Pos2 is completely in Pos1
+ case SwComparePosition::Equal: // Pos1 has same size as Pos2
+ break;
+
+ case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 at beginning
+ if( !pCur->HasMark() )
+ pCur->SetMark();
+ *pCEnd = *pNEnd;
+ break;
+ case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at end
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ break;
+
+ default:
+ bDel = false;
+ }
+
+ if( bDel )
+ {
+ // not needed anymore
+ SwPaM* pPrevPam = pNextPam->GetPrev();
+ delete pNextPam;
+ pNextPam = pPrevPam;
+ }
+ pNextPam = pNextPam->GetNext();
+ }
+ }
+
+ SwRedlineTable::size_type nFndPos = 2 == nLoopCnt
+ ? rTable.FindNextOfSeqNo( nArrPos )
+ : rTable.FindPrevOfSeqNo( nArrPos );
+ if( SwRedlineTable::npos != nFndPos ||
+ ( 0 != ( --nLoopCnt ) && SwRedlineTable::npos != (
+ nFndPos = rTable.FindPrevOfSeqNo( nArrSavPos ))) )
+ {
+ if( pTmp )
+ {
+ // create new cursor
+ CreateCursor();
+ bCheck = true;
+ }
+ nArrPos = nFndPos;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+ }
+ else
+ pFnd = GotoRedline_( nArrPos, bSelect );
+ }
+ return pFnd;
+}
+
+bool SwCursorShell::SelectNxtPrvHyperlink( bool bNext )
+{
+ SwNodes& rNds = GetDoc()->GetNodes();
+ const SwNode* pBodyEndNd = &rNds.GetEndOfContent();
+ const SwNode* pBodySttNd = pBodyEndNd->StartOfSectionNode();
+ SwNodeOffset nBodySttNdIdx = pBodySttNd->GetIndex();
+ Point aPt;
+
+ SetGetExpField aCmpPos( SwPosition( bNext ? *pBodyEndNd : *pBodySttNd ) );
+ SetGetExpField aCurPos( bNext ? *m_pCurrentCursor->End() : *m_pCurrentCursor->Start() );
+ if( aCurPos.GetNode() < nBodySttNdIdx )
+ {
+ const SwContentNode* pCNd = aCurPos.GetNodeFromContent()->GetContentNode();
+ std::pair<Point, bool> tmp(aPt, true);
+ if (pCNd)
+ {
+ SwContentFrame* pFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if( pFrame )
+ aCurPos.SetBodyPos( *pFrame );
+ }
+ }
+
+ // check first all the hyperlink fields
+ {
+ const SwTextNode* pTextNd;
+ const SwCharFormats* pFormats = GetDoc()->GetCharFormats();
+ for( SwCharFormats::size_type n = pFormats->size(); 1 < n; )
+ {
+ SwIterator<SwTextINetFormat,SwCharFormat> aIter(*(*pFormats)[--n]);
+
+ for( SwTextINetFormat* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ {
+ pTextNd = pFnd->GetpTextNode();
+ if( pTextNd && pTextNd->GetNodes().IsDocNodes() )
+ {
+ SwTextINetFormat& rAttr = *pFnd;
+ SwPosition aTmpPos( *pTextNd );
+ SetGetExpField aPos( aTmpPos.nNode, rAttr );
+ if (pTextNd->GetIndex() < nBodySttNdIdx)
+ {
+ std::pair<Point, bool> tmp(aPt, true);
+ SwContentFrame* pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
+ if (pFrame)
+ {
+ aPos.SetBodyPos( *pFrame );
+ }
+ }
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ {
+ OUString sText(pTextNd->GetExpandText(GetLayout(),
+ rAttr.GetStart(),
+ *rAttr.GetEnd() - rAttr.GetStart() ) );
+
+ sText = sText.replaceAll("\x0a", "");
+ sText = comphelper::string::strip(sText, ' ');
+
+ if( !sText.isEmpty() )
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+ }
+
+ // then check all the Flys with a URL or image map
+ {
+ const SwFrameFormats* pFormats = GetDoc()->GetSpzFrameFormats();
+ for( SwFrameFormats::size_type n = 0, nEnd = pFormats->size(); n < nEnd; ++n )
+ {
+ SwFlyFrameFormat* pFormat = static_cast<SwFlyFrameFormat*>((*pFormats)[ n ]);
+ const SwFormatURL& rURLItem = pFormat->GetURL();
+ if( rURLItem.GetMap() || !rURLItem.GetURL().isEmpty() )
+ {
+ SwFlyFrame* pFly = pFormat->GetFrame( &aPt );
+ SwPosition aTmpPos( *pBodySttNd );
+ if( pFly &&
+ GetBodyTextNode( *GetDoc(), aTmpPos, *pFly->GetLower() ) )
+ {
+ SetGetExpField aPos( *pFormat, &aTmpPos );
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+
+ // found any URL ?
+ bool bRet = false;
+ const SwTextINetFormat* pFndAttr = aCmpPos.GetINetFormat();
+ const SwFlyFrameFormat* pFndFormat = aCmpPos.GetFlyFormat();
+ if( pFndAttr || pFndFormat )
+ {
+ CurrShell aCurr( this );
+ SwCallLink aLk( *this );
+
+ // found a text attribute ?
+ if( pFndAttr )
+ {
+ SwCursorSaveState aSaveState( *m_pCurrentCursor );
+
+ aCmpPos.GetPosOfContent( *m_pCurrentCursor->GetPoint() );
+ m_pCurrentCursor->DeleteMark();
+ m_pCurrentCursor->SetMark();
+ m_pCurrentCursor->GetPoint()->nContent = *pFndAttr->End();
+
+ if( !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() )
+ {
+ UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|
+ SwCursorShell::READONLY );
+ bRet = true;
+ }
+ }
+ // found a draw object ?
+ else if( RES_DRAWFRMFMT == pFndFormat->Which() )
+ {
+ const SdrObject* pSObj = pFndFormat->FindSdrObject();
+ if (pSObj)
+ {
+ static_cast<SwFEShell*>(this)->SelectObj( pSObj->GetCurrentBoundRect().Center() );
+ MakeSelVisible();
+ bRet = true;
+ }
+ }
+ else // then is it a fly
+ {
+ SwFlyFrame* pFly = pFndFormat->GetFrame(&aPt);
+ if( pFly )
+ {
+ static_cast<SwFEShell*>(this)->SelectFlyFrame( *pFly );
+ MakeSelVisible();
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */