Add a comment to clarify what kind of inputs the class handles
[LibreOffice.git] / sw / source / core / crsr / trvlfnfl.cxx
blob060d754fd82cf26e695afcb0e53feff775303a59
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <crsrsh.hxx>
21 #include <doc.hxx>
22 #include <pagefrm.hxx>
23 #include <cntfrm.hxx>
24 #include <ftnfrm.hxx>
25 #include <swcrsr.hxx>
26 #include <ndtxt.hxx>
27 #include <txtfrm.hxx>
28 #include <txtftn.hxx>
29 #include <ftnidx.hxx>
30 #include <viscrs.hxx>
31 #include "callnk.hxx"
32 #include <svx/srchdlg.hxx>
33 #include <wrtsh.hxx>
35 bool SwCursorShell::CallCursorShellFN( FNCursorShell fnCursor )
37 SwCallLink aLk( *this ); // watch Cursor-Moves
38 bool bRet = (this->*fnCursor)();
39 if( bRet )
40 UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
41 SwCursorShell::READONLY );
42 return bRet;
45 bool SwCursorShell::CallCursorFN( FNCursor fnCursor )
47 // for footnote anchor<->text recency
48 if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this))
49 pWrtSh->addCurrentPosition();
51 SwCallLink aLk( *this ); // watch Cursor-Moves
52 SwCursor* pCursor = getShellCursor( true );
53 bool bRet = (pCursor->*fnCursor)();
54 if( bRet )
55 UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
56 SwCursorShell::READONLY );
57 return bRet;
60 bool SwCursor::GotoFootnoteText()
62 // jump from content to footnote
63 bool bRet = false;
64 SwTextNode* pTextNd = GetPoint()->GetNode().GetTextNode();
66 SwTextAttr *const pFootnote( pTextNd
67 ? pTextNd->GetTextAttrForCharAt(
68 GetPoint()->GetContentIndex(), RES_TXTATR_FTN)
69 : nullptr);
70 if (pFootnote)
72 SwCursorSaveState aSaveState( *this );
73 GetPoint()->Assign( *static_cast<SwTextFootnote*>(pFootnote)->GetStartNode() );
75 SwContentNode* pCNd = SwNodes::GoNextSection(
76 GetPoint(),
77 true, !IsReadOnlyAvailable() );
78 if( pCNd )
80 bRet = !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
81 SwCursorSelOverFlags::Toggle );
84 return bRet;
87 bool SwCursorShell::GotoFootnoteText()
89 bool bRet = CallCursorFN( &SwCursor::GotoFootnoteText );
90 if( !bRet )
92 SwTextNode* pTextNd = GetCursor_() ?
93 GetCursor_()->GetPoint()->GetNode().GetTextNode() : nullptr;
94 if( pTextNd )
96 std::pair<Point, bool> const tmp(GetCursor_()->GetSttPos(), true);
97 const SwFrame *pFrame = pTextNd->getLayoutFrame( GetLayout(),
98 GetCursor_()->Start(), &tmp);
99 const SwFootnoteBossFrame* pFootnoteBoss;
100 bool bSkip = pFrame && pFrame->IsInFootnote();
101 while( pFrame )
103 pFootnoteBoss = pFrame->FindFootnoteBossFrame();
104 if (!pFootnoteBoss)
105 break;
106 pFrame = pFootnoteBoss->FindFootnoteCont();
107 if( pFrame )
109 if( bSkip )
110 bSkip = false;
111 else
113 const SwContentFrame* pCnt = static_cast<const SwLayoutFrame*>
114 (pFrame)->ContainsContent();
115 if( pCnt )
117 SwTextFrame const*const pTF(
118 static_cast<const SwTextFrame*>(pCnt));
119 *GetCursor_()->GetPoint() =
120 pTF->MapViewToModelPos(pTF->GetOffset());
121 UpdateCursor( SwCursorShell::SCROLLWIN |
122 SwCursorShell::CHKRANGE | SwCursorShell::READONLY );
123 bRet = true;
124 break;
128 if( pFootnoteBoss->GetNext() && !pFootnoteBoss->IsPageFrame() )
129 pFrame = pFootnoteBoss->GetNext();
130 else
131 pFrame = pFootnoteBoss->GetUpper();
135 return bRet;
138 bool SwCursor::GotoFootnoteAnchor()
140 // jump from footnote to anchor
141 const SwNode* pSttNd = GetPointNode().FindFootnoteStartNode();
142 if( pSttNd )
144 // search in all footnotes in document for this StartIndex
145 const SwFootnoteIdxs& rFootnoteArr = pSttNd->GetDoc().GetFootnoteIdxs();
146 for( size_t n = 0; n < rFootnoteArr.size(); ++n )
148 const SwTextFootnote* pTextFootnote = rFootnoteArr[ n ];
149 if( nullptr != pTextFootnote->GetStartNode() &&
150 pSttNd == &pTextFootnote->GetStartNode()->GetNode() )
152 SwCursorSaveState aSaveState( *this );
154 SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode());
155 GetPoint()->Assign( rTNd, pTextFootnote->GetStart() );
157 return !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
158 SwCursorSelOverFlags::Toggle );
162 return false;
165 bool SwCursorShell::GotoFootnoteAnchor()
167 if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this))
168 pWrtSh->addCurrentPosition();
170 // jump from footnote to anchor
171 SwCallLink aLk( *this ); // watch Cursor-Moves
172 bool bRet = m_pCurrentCursor->GotoFootnoteAnchor();
173 if( bRet )
175 // special treatment for table header row
176 m_pCurrentCursor->GetPtPos() = Point();
177 UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
178 SwCursorShell::READONLY );
180 return bRet;
183 static bool CmpLE( const SwTextFootnote& rFootnote, SwNodeOffset nNd, sal_Int32 nCnt )
185 const SwNodeOffset nTNd = rFootnote.GetTextNode().GetIndex();
186 return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() <= nCnt );
189 static bool CmpL( const SwTextFootnote& rFootnote, SwNodeOffset nNd, sal_Int32 nCnt )
191 const SwNodeOffset nTNd = rFootnote.GetTextNode().GetIndex();
192 return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() < nCnt );
195 bool SwCursor::GotoNextFootnoteAnchor()
197 const SwFootnoteIdxs& rFootnoteArr = GetDoc().GetFootnoteIdxs();
198 const SwTextFootnote* pTextFootnote = nullptr;
199 size_t nPos = 0;
201 if( rFootnoteArr.empty() )
203 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
204 return false;
207 if( rFootnoteArr.SeekEntry( GetPoint()->GetNode(), &nPos ))
209 // there is a footnote with this index, so search also for the next one
210 if( nPos < rFootnoteArr.size() )
212 SwNodeOffset nNdPos = GetPoint()->GetNodeIndex();
213 const sal_Int32 nCntPos = GetPoint()->GetContentIndex();
215 pTextFootnote = rFootnoteArr[ nPos ];
216 // search forwards
217 if( CmpLE( *pTextFootnote, nNdPos, nCntPos ) )
219 pTextFootnote = nullptr;
220 for( ++nPos; nPos < rFootnoteArr.size(); ++nPos )
222 pTextFootnote = rFootnoteArr[ nPos ];
223 if( !CmpLE( *pTextFootnote, nNdPos, nCntPos ) )
224 break; // found
225 pTextFootnote = nullptr;
228 else if( nPos )
230 // search backwards
231 pTextFootnote = nullptr;
232 while (nPos > 0)
234 pTextFootnote = rFootnoteArr[ --nPos ];
235 if( CmpLE( *pTextFootnote, nNdPos, nCntPos ) )
237 pTextFootnote = rFootnoteArr[ ++nPos ];
238 break; // found
244 else if( nPos < rFootnoteArr.size() )
245 pTextFootnote = rFootnoteArr[ nPos ];
247 if (pTextFootnote == nullptr)
249 pTextFootnote = rFootnoteArr[ 0 ];
250 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
252 else
253 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
255 bool bRet = nullptr != pTextFootnote;
256 if( bRet )
258 SwCursorSaveState aSaveState( *this );
260 SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode());
261 GetPoint()->Assign( rTNd, pTextFootnote->GetStart() );
262 bRet = !IsSelOvr();
264 return bRet;
267 bool SwCursor::GotoPrevFootnoteAnchor()
269 const SwFootnoteIdxs& rFootnoteArr = GetDoc().GetFootnoteIdxs();
270 const SwTextFootnote* pTextFootnote = nullptr;
271 size_t nPos = 0;
273 if( rFootnoteArr.empty() )
275 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
276 return false;
279 if( rFootnoteArr.SeekEntry( GetPoint()->GetNode(), &nPos ) )
281 // there is a footnote with this index, so search also for the next one
282 SwNodeOffset nNdPos = GetPoint()->GetNodeIndex();
283 const sal_Int32 nCntPos = GetPoint()->GetContentIndex();
285 pTextFootnote = rFootnoteArr[ nPos ];
286 // search forwards
287 if( CmpL( *pTextFootnote, nNdPos, nCntPos ))
289 for( ++nPos; nPos < rFootnoteArr.size(); ++nPos )
291 pTextFootnote = rFootnoteArr[ nPos ];
292 if( !CmpL( *pTextFootnote, nNdPos, nCntPos ) )
294 pTextFootnote = rFootnoteArr[ nPos-1 ];
295 break;
299 else if (nPos > 0)
301 // search backwards
302 pTextFootnote = nullptr;
303 while (nPos > 0)
305 --nPos;
306 pTextFootnote = rFootnoteArr[nPos];
307 if( CmpL( *pTextFootnote, nNdPos, nCntPos ))
308 break; // found
309 pTextFootnote = nullptr;
312 else
313 pTextFootnote = nullptr;
315 else if (nPos > 0)
316 pTextFootnote = rFootnoteArr[ nPos-1 ];
318 if( pTextFootnote == nullptr )
320 pTextFootnote = rFootnoteArr[ rFootnoteArr.size() - 1 ];
321 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
323 else
324 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
326 bool bRet = nullptr != pTextFootnote;
327 if( bRet )
329 SwCursorSaveState aSaveState( *this );
331 SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode());
332 GetPoint()->Assign( rTNd, pTextFootnote->GetStart() );
333 bRet = !IsSelOvr();
335 return bRet;
338 bool SwCursorShell::GotoNextFootnoteAnchor()
340 return CallCursorFN( &SwCursor::GotoNextFootnoteAnchor );
343 bool SwCursorShell::GotoPrevFootnoteAnchor()
345 return CallCursorFN( &SwCursor::GotoPrevFootnoteAnchor );
348 /// jump from border to anchor
349 void SwCursorShell::GotoFlyAnchor()
351 CurrShell aCurr( this );
352 const SwFrame* pFrame = GetCurrFrame();
353 do {
354 pFrame = pFrame->GetUpper();
355 } while( pFrame && !pFrame->IsFlyFrame() );
357 if( !pFrame ) // no FlyFrame
358 return;
360 SwCallLink aLk( *this ); // watch Cursor-Moves
361 SwCursorSaveState aSaveState( *m_pCurrentCursor );
363 // jump in BodyFrame closest to FlyFrame
364 SwRect aTmpRect( m_aCharRect );
365 if( !pFrame->getFrameArea().Contains( aTmpRect ))
366 aTmpRect = pFrame->getFrameArea();
367 Point aPt( aTmpRect.Left(), aTmpRect.Top() +
368 ( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 );
369 aPt.setX(aPt.getX() > (pFrame->getFrameArea().Left() + (pFrame->getFrameArea().SSize().Width() / 2 ))
370 ? pFrame->getFrameArea().Right()
371 : pFrame->getFrameArea().Left());
373 const SwPageFrame* pPageFrame = pFrame->FindPageFrame();
374 const SwContentFrame* pFndFrame = pPageFrame->GetContentPos( aPt, false, true );
375 pFndFrame->GetModelPositionForViewPoint( m_pCurrentCursor->GetPoint(), aPt );
377 bool bRet = !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr();
378 if( bRet )
379 UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
380 SwCursorShell::READONLY );
383 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */