blob: d92bca800036d97f0e870d41fe71408cf90c5de5 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
#include <crsrsh.hxx>
#include <doc.hxx>
#include <pagefrm.hxx>
#include <cntfrm.hxx>
#include <ftnfrm.hxx>
#include <viewimp.hxx>
#include <swcrsr.hxx>
#include <dflyobj.hxx>
#include <ndtxt.hxx>
#include <flyfrm.hxx>
#include <txtfrm.hxx>
#include <txtftn.hxx>
#include <ftnidx.hxx>
#include <viscrs.hxx>
#include <callnk.hxx>
sal_Bool SwCrsrShell::CallCrsrFN( FNCrsr fnCrsr )
{
SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
SwCursor* pCrsr = getShellCrsr( true );
sal_Bool bRet = (pCrsr->*fnCrsr)();
if( bRet )
UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
SwCrsrShell::READONLY );
return bRet;
}
sal_Bool SwCursor::GotoFtnTxt()
{
// springe aus dem Content zur Fussnote
sal_Bool bRet = sal_False;
SwTxtNode* pTxtNd = GetPoint()->nNode.GetNode().GetTxtNode();
SwTxtAttr *const pFtn( (pTxtNd)
? pTxtNd->GetTxtAttrForCharAt(
GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN)
: 0);
if (pFtn)
{
SwCrsrSaveState aSaveState( *this );
GetPoint()->nNode = *((SwTxtFtn*)pFtn)->GetStartNode();
SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
&GetPoint()->nNode,
sal_True, !IsReadOnlyAvailable() );
if( pCNd )
{
GetPoint()->nContent.Assign( pCNd, 0 );
bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
nsSwCursorSelOverFlags::SELOVER_TOGGLE );
}
}
return bRet;
}
sal_Bool SwCrsrShell::GotoFtnTxt()
{
sal_Bool bRet = CallCrsrFN( &SwCursor::GotoFtnTxt );
if( !bRet )
{
SwTxtNode* pTxtNd = _GetCrsr() ?
_GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode() : NULL;
if( pTxtNd )
{
const SwFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &_GetCrsr()->GetSttPos(),
_GetCrsr()->Start() );
const SwFtnBossFrm* pFtnBoss;
sal_Bool bSkip = pFrm && pFrm->IsInFtn();
while( pFrm && 0 != ( pFtnBoss = pFrm->FindFtnBossFrm() ) )
{
if( 0 != ( pFrm = pFtnBoss->FindFtnCont() ) )
{
if( bSkip )
bSkip = sal_False;
else
{
const SwCntntFrm* pCnt = static_cast<const SwLayoutFrm*>
(pFrm)->ContainsCntnt();
if( pCnt )
{
const SwCntntNode* pNode = pCnt->GetNode();
_GetCrsr()->GetPoint()->nNode = *pNode;
_GetCrsr()->GetPoint()->nContent.Assign(
const_cast<SwCntntNode*>(pNode),
static_cast<const SwTxtFrm*>(pCnt)->GetOfst() );
UpdateCrsr( SwCrsrShell::SCROLLWIN |
SwCrsrShell::CHKRANGE | SwCrsrShell::READONLY );
bRet = sal_True;
break;
}
}
}
if( pFtnBoss->GetNext() && !pFtnBoss->IsPageFrm() )
pFrm = pFtnBoss->GetNext();
else
pFrm = pFtnBoss->GetUpper();
}
}
}
return bRet;
}
sal_Bool SwCursor::GotoFtnAnchor()
{
// springe aus der Fussnote zum Anker
const SwNode* pSttNd = GetNode()->FindFootnoteStartNode();
if( pSttNd )
{
// durchsuche alle Fussnoten im Dokument nach diesem StartIndex
const SwTxtFtn* pTxtFtn;
const SwFtnIdxs& rFtnArr = pSttNd->GetDoc()->GetFtnIdxs();
for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
pSttNd == &pTxtFtn->GetStartNode()->GetNode() )
{
SwCrsrSaveState aSaveState( *this );
SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
GetPoint()->nNode = rTNd;
GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
return !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
nsSwCursorSelOverFlags::SELOVER_TOGGLE );
}
}
return sal_False;
}
sal_Bool SwCrsrShell::GotoFtnAnchor()
{
// springe aus der Fussnote zum Anker
SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
sal_Bool bRet = pCurCrsr->GotoFtnAnchor();
if( bRet )
{
// BUG 5996: Tabellen-Kopfzeile sonderbehandeln
pCurCrsr->GetPtPos() = Point();
UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
SwCrsrShell::READONLY );
}
return bRet;
}
inline sal_Bool CmpLE( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
{
sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() <= nCnt );
}
inline sal_Bool CmpL( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
{
sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() < nCnt );
}
sal_Bool SwCursor::GotoNextFtnAnchor()
{
const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
const SwTxtFtn* pTxtFtn = 0;
sal_uInt16 nPos;
if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ))
{
// es gibt eine Fussnote mit dem Index, suche also die
// naechstgelegene
if( nPos < rFtnArr.Count() )
{
sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
pTxtFtn = rFtnArr[ nPos ];
// suche vorewaerts zur naechsten
if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
{
pTxtFtn = 0;
for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
{
pTxtFtn = rFtnArr[ nPos ];
if( !CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
break; // gefunden
pTxtFtn = 0;
}
}
else if( nPos )
{
// suche rueckwaerts zur vorherigen
pTxtFtn = 0;
while( nPos )
{
pTxtFtn = rFtnArr[ --nPos ];
if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
{
pTxtFtn = rFtnArr[ ++nPos ];
break; // gefunden
}
// pTxtFtn = 0;
}
}
}
}
else if( nPos < rFtnArr.Count() )
pTxtFtn = rFtnArr[ nPos ];
sal_Bool bRet = 0 != pTxtFtn;
if( bRet )
{
SwCrsrSaveState aSaveState( *this );
SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
GetPoint()->nNode = rTNd;
GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
bRet = !IsSelOvr();
}
return bRet;
}
sal_Bool SwCursor::GotoPrevFtnAnchor()
{
const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
const SwTxtFtn* pTxtFtn = 0;
sal_uInt16 nPos;
if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ) )
{
// es gibt eine Fussnote mit dem Index, suche also die
// naechstgelegene
sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
pTxtFtn = rFtnArr[ nPos ];
// suche vorwaerts zur naechsten
if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
{
for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
{
pTxtFtn = rFtnArr[ nPos ];
if( !CmpL( *pTxtFtn, nNdPos, nCntPos ) )
{
pTxtFtn = rFtnArr[ nPos-1 ];
break;
}
}
}
else if( nPos )
{
// suche rueckwaerts zur vorherigen
pTxtFtn = 0;
while( nPos )
{
pTxtFtn = rFtnArr[ --nPos ];
if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
break; // gefunden
pTxtFtn = 0;
}
}
else
pTxtFtn = 0;
}
else if( nPos )
pTxtFtn = rFtnArr[ nPos-1 ];
sal_Bool bRet = 0 != pTxtFtn;
if( bRet )
{
SwCrsrSaveState aSaveState( *this );
SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
GetPoint()->nNode = rTNd;
GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
bRet = !IsSelOvr();
}
return bRet;
}
sal_Bool SwCrsrShell::GotoNextFtnAnchor()
{
return CallCrsrFN( &SwCursor::GotoNextFtnAnchor );
}
sal_Bool SwCrsrShell::GotoPrevFtnAnchor()
{
return CallCrsrFN( &SwCursor::GotoPrevFtnAnchor );
}
// springe aus dem Rahmen zum Anker
sal_Bool SwCrsrShell::GotoFlyAnchor()
{
SET_CURR_SHELL( this );
const SwFrm* pFrm = GetCurrFrm();
do {
pFrm = pFrm->GetUpper();
} while( pFrm && !pFrm->IsFlyFrm() );
if( !pFrm ) // ist kein FlyFrame
return sal_False;
SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
SwCrsrSaveState aSaveState( *pCurCrsr );
// springe in den BodyFrame, der am naechsten vom Fly liegt
SwRect aTmpRect( aCharRect );
if( !pFrm->Frm().IsInside( aTmpRect ))
aTmpRect = pFrm->Frm();
Point aPt( aTmpRect.Left(), aTmpRect.Top() +
( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 );
aPt.X() = aPt.X() > (pFrm->Frm().Left() + (pFrm->Frm().SSize().Width() / 2 ))
? pFrm->Frm().Right()
: pFrm->Frm().Left();
const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
const SwCntntFrm* pFndFrm = pPageFrm->GetCntntPos( aPt, sal_False, sal_True );
pFndFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
sal_Bool bRet = !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr();
if( bRet )
UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
SwCrsrShell::READONLY );
return bRet;
}