diff options
Diffstat (limited to 'sw/source/core/crsr/trvlfnfl.cxx')
-rw-r--r-- | sw/source/core/crsr/trvlfnfl.cxx | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/sw/source/core/crsr/trvlfnfl.cxx b/sw/source/core/crsr/trvlfnfl.cxx new file mode 100644 index 000000000..e0eb9ca48 --- /dev/null +++ b/sw/source/core/crsr/trvlfnfl.cxx @@ -0,0 +1,378 @@ +/* -*- 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 <crsrsh.hxx> +#include <doc.hxx> +#include <pagefrm.hxx> +#include <cntfrm.hxx> +#include <ftnfrm.hxx> +#include <swcrsr.hxx> +#include <ndtxt.hxx> +#include <txtfrm.hxx> +#include <txtftn.hxx> +#include <ftnidx.hxx> +#include <viscrs.hxx> +#include "callnk.hxx" +#include <svx/srchdlg.hxx> + +bool SwCursorShell::CallCursorShellFN( FNCursorShell fnCursor ) +{ + SwCallLink aLk( *this ); // watch Cursor-Moves + bool bRet = (this->*fnCursor)(); + if( bRet ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); + return bRet; +} + +bool SwCursorShell::CallCursorFN( FNCursor fnCursor ) +{ + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursor* pCursor = getShellCursor( true ); + bool bRet = (pCursor->*fnCursor)(); + if( bRet ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); + return bRet; +} + +bool SwCursor::GotoFootnoteText() +{ + // jump from content to footnote + bool bRet = false; + SwTextNode* pTextNd = GetPoint()->nNode.GetNode().GetTextNode(); + + SwTextAttr *const pFootnote( pTextNd + ? pTextNd->GetTextAttrForCharAt( + GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN) + : nullptr); + if (pFootnote) + { + SwCursorSaveState aSaveState( *this ); + GetPoint()->nNode = *static_cast<SwTextFootnote*>(pFootnote)->GetStartNode(); + + SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( + &GetPoint()->nNode, + true, !IsReadOnlyAvailable() ); + if( pCNd ) + { + GetPoint()->nContent.Assign( pCNd, 0 ); + bRet = !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | + SwCursorSelOverFlags::Toggle ); + } + } + return bRet; +} + +bool SwCursorShell::GotoFootnoteText() +{ + bool bRet = CallCursorFN( &SwCursor::GotoFootnoteText ); + if( !bRet ) + { + SwTextNode* pTextNd = GetCursor_() ? + GetCursor_()->GetPoint()->nNode.GetNode().GetTextNode() : nullptr; + if( pTextNd ) + { + std::pair<Point, bool> const tmp(GetCursor_()->GetSttPos(), true); + const SwFrame *pFrame = pTextNd->getLayoutFrame( GetLayout(), + GetCursor_()->Start(), &tmp); + const SwFootnoteBossFrame* pFootnoteBoss; + bool bSkip = pFrame && pFrame->IsInFootnote(); + while( pFrame ) + { + pFootnoteBoss = pFrame->FindFootnoteBossFrame(); + if (!pFootnoteBoss) + break; + pFrame = pFootnoteBoss->FindFootnoteCont(); + if( pFrame ) + { + if( bSkip ) + bSkip = false; + else + { + const SwContentFrame* pCnt = static_cast<const SwLayoutFrame*> + (pFrame)->ContainsContent(); + if( pCnt ) + { + SwTextFrame const*const pTF( + static_cast<const SwTextFrame*>(pCnt)); + *GetCursor_()->GetPoint() = + pTF->MapViewToModelPos(pTF->GetOffset()); + UpdateCursor( SwCursorShell::SCROLLWIN | + SwCursorShell::CHKRANGE | SwCursorShell::READONLY ); + bRet = true; + break; + } + } + } + if( pFootnoteBoss->GetNext() && !pFootnoteBoss->IsPageFrame() ) + pFrame = pFootnoteBoss->GetNext(); + else + pFrame = pFootnoteBoss->GetUpper(); + } + } + } + return bRet; +} + +bool SwCursor::GotoFootnoteAnchor() +{ + // jump from footnote to anchor + const SwNode* pSttNd = GetNode().FindFootnoteStartNode(); + if( pSttNd ) + { + // search in all footnotes in document for this StartIndex + const SwFootnoteIdxs& rFootnoteArr = pSttNd->GetDoc()->GetFootnoteIdxs(); + for( size_t n = 0; n < rFootnoteArr.size(); ++n ) + { + const SwTextFootnote* pTextFootnote = rFootnoteArr[ n ]; + if( nullptr != pTextFootnote->GetStartNode() && + pSttNd == &pTextFootnote->GetStartNode()->GetNode() ) + { + SwCursorSaveState aSaveState( *this ); + + SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); + GetPoint()->nNode = rTNd; + GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + + return !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | + SwCursorSelOverFlags::Toggle ); + } + } + } + return false; +} + +bool SwCursorShell::GotoFootnoteAnchor() +{ + // jump from footnote to anchor + SwCallLink aLk( *this ); // watch Cursor-Moves + bool bRet = m_pCurrentCursor->GotoFootnoteAnchor(); + if( bRet ) + { + // special treatment for table header row + m_pCurrentCursor->GetPtPos() = Point(); + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); + } + return bRet; +} + +static bool CmpLE( const SwTextFootnote& rFootnote, sal_uLong nNd, sal_Int32 nCnt ) +{ + const sal_uLong nTNd = rFootnote.GetTextNode().GetIndex(); + return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() <= nCnt ); +} + +static bool CmpL( const SwTextFootnote& rFootnote, sal_uLong nNd, sal_Int32 nCnt ) +{ + const sal_uLong nTNd = rFootnote.GetTextNode().GetIndex(); + return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() < nCnt ); +} + +bool SwCursor::GotoNextFootnoteAnchor() +{ + const SwFootnoteIdxs& rFootnoteArr = GetDoc()->GetFootnoteIdxs(); + const SwTextFootnote* pTextFootnote = nullptr; + size_t nPos = 0; + + if( rFootnoteArr.empty() ) + { + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + return false; + } + + if( rFootnoteArr.SeekEntry( GetPoint()->nNode, &nPos )) + { + // there is a footnote with this index, so search also for the next one + if( nPos < rFootnoteArr.size() ) + { + sal_uLong nNdPos = GetPoint()->nNode.GetIndex(); + const sal_Int32 nCntPos = GetPoint()->nContent.GetIndex(); + + pTextFootnote = rFootnoteArr[ nPos ]; + // search forwards + if( CmpLE( *pTextFootnote, nNdPos, nCntPos ) ) + { + pTextFootnote = nullptr; + for( ++nPos; nPos < rFootnoteArr.size(); ++nPos ) + { + pTextFootnote = rFootnoteArr[ nPos ]; + if( !CmpLE( *pTextFootnote, nNdPos, nCntPos ) ) + break; // found + pTextFootnote = nullptr; + } + } + else if( nPos ) + { + // search backwards + pTextFootnote = nullptr; + while( nPos ) + { + pTextFootnote = rFootnoteArr[ --nPos ]; + if( CmpLE( *pTextFootnote, nNdPos, nCntPos ) ) + { + pTextFootnote = rFootnoteArr[ ++nPos ]; + break; // found + } + } + } + } + } + else if( nPos < rFootnoteArr.size() ) + pTextFootnote = rFootnoteArr[ nPos ]; + + if (pTextFootnote == nullptr) + { + pTextFootnote = rFootnoteArr[ 0 ]; + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); + } + else + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + + bool bRet = nullptr != pTextFootnote; + if( bRet ) + { + SwCursorSaveState aSaveState( *this ); + + SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); + GetPoint()->nNode = rTNd; + GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + bRet = !IsSelOvr(); + } + return bRet; +} + +bool SwCursor::GotoPrevFootnoteAnchor() +{ + const SwFootnoteIdxs& rFootnoteArr = GetDoc()->GetFootnoteIdxs(); + const SwTextFootnote* pTextFootnote = nullptr; + size_t nPos = 0; + + if( rFootnoteArr.empty() ) + { + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + return false; + } + + if( rFootnoteArr.SeekEntry( GetPoint()->nNode, &nPos ) ) + { + // there is a footnote with this index, so search also for the next one + sal_uLong nNdPos = GetPoint()->nNode.GetIndex(); + const sal_Int32 nCntPos = GetPoint()->nContent.GetIndex(); + + pTextFootnote = rFootnoteArr[ nPos ]; + // search forwards + if( CmpL( *pTextFootnote, nNdPos, nCntPos )) + { + for( ++nPos; nPos < rFootnoteArr.size(); ++nPos ) + { + pTextFootnote = rFootnoteArr[ nPos ]; + if( !CmpL( *pTextFootnote, nNdPos, nCntPos ) ) + { + pTextFootnote = rFootnoteArr[ nPos-1 ]; + break; + } + } + } + else if( nPos ) + { + // search backwards + pTextFootnote = nullptr; + while( nPos ) + { + pTextFootnote = rFootnoteArr[ --nPos ]; + if( CmpL( *pTextFootnote, nNdPos, nCntPos )) + break; // found + pTextFootnote = nullptr; + } + } + else + pTextFootnote = nullptr; + } + else if( nPos ) + pTextFootnote = rFootnoteArr[ nPos-1 ]; + + if( pTextFootnote == nullptr ) + { + pTextFootnote = rFootnoteArr[ rFootnoteArr.size() - 1 ]; + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); + } + else + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + + bool bRet = nullptr != pTextFootnote; + if( bRet ) + { + SwCursorSaveState aSaveState( *this ); + + SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); + GetPoint()->nNode = rTNd; + GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + bRet = !IsSelOvr(); + } + return bRet; +} + +bool SwCursorShell::GotoNextFootnoteAnchor() +{ + return CallCursorFN( &SwCursor::GotoNextFootnoteAnchor ); +} + +bool SwCursorShell::GotoPrevFootnoteAnchor() +{ + return CallCursorFN( &SwCursor::GotoPrevFootnoteAnchor ); +} + +/// jump from border to anchor +void SwCursorShell::GotoFlyAnchor() +{ + SET_CURR_SHELL( this ); + const SwFrame* pFrame = GetCurrFrame(); + do { + pFrame = pFrame->GetUpper(); + } while( pFrame && !pFrame->IsFlyFrame() ); + + if( !pFrame ) // no FlyFrame + return; + + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + + // jump in BodyFrame closest to FlyFrame + SwRect aTmpRect( m_aCharRect ); + if( !pFrame->getFrameArea().IsInside( aTmpRect )) + aTmpRect = pFrame->getFrameArea(); + Point aPt( aTmpRect.Left(), aTmpRect.Top() + + ( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 ); + aPt.setX(aPt.getX() > (pFrame->getFrameArea().Left() + (pFrame->getFrameArea().SSize().Width() / 2 )) + ? pFrame->getFrameArea().Right() + : pFrame->getFrameArea().Left()); + + const SwPageFrame* pPageFrame = pFrame->FindPageFrame(); + const SwContentFrame* pFndFrame = pPageFrame->GetContentPos( aPt, false, true ); + pFndFrame->GetModelPositionForViewPoint( m_pCurrentCursor->GetPoint(), aPt ); + + bool bRet = !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr(); + if( bRet ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |