1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sfx2/bindings.hxx>
21 #include <sfx2/viewfrm.hxx>
24 #include <viewopt.hxx>
25 #include <drawbase.hxx>
29 - Reset of the cursor stack
31 - if applicable: GCAttr
40 const tools::Long nReadOnlyScrollOfst
= 10;
49 ShellMoveCursor( SwWrtShell
* pWrtSh
, bool bSel
)
51 bAct
= !pWrtSh
->ActionPend() && (pWrtSh
->GetFrameType(nullptr,false) & FrameTypeFlags::FLY_ANY
);
53 pSh
->MoveCursor( bSel
);
54 pWrtSh
->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK
);
56 ~ShellMoveCursor() COVERITY_NOEXCEPT_FALSE
60 // The action is used for scrolling in "single paragraph"
61 // frames with fixed height.
62 pSh
->StartAllAction();
70 void SwWrtShell::MoveCursor( bool bWithSelect
)
83 (this->*m_fnKillSel
)( nullptr, false );
87 bool SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove
, bool bSelect
)
94 bRet
= (this->*FnSimpleMove
)();
99 bRet
= (this->*FnSimpleMove
)();
106 bool SwWrtShell::Left( sal_uInt16 nMode
, bool bSelect
,
107 sal_uInt16 nCount
, bool bBasicCall
, bool bVisual
)
109 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
111 Point
aTmp( VisArea().Pos() );
112 aTmp
.AdjustX( -(VisArea().Width() * nReadOnlyScrollOfst
/ 100) );
113 m_rView
.SetVisArea( aTmp
);
118 ShellMoveCursor
aTmp( this, bSelect
);
119 return SwCursorShell::Left( nCount
, nMode
, bVisual
);
123 bool SwWrtShell::Right( sal_uInt16 nMode
, bool bSelect
,
124 sal_uInt16 nCount
, bool bBasicCall
, bool bVisual
)
126 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
128 Point
aTmp( VisArea().Pos() );
129 aTmp
.AdjustX(VisArea().Width() * nReadOnlyScrollOfst
/ 100 );
130 aTmp
.setX( m_rView
.SetHScrollMax( aTmp
.X() ) );
131 m_rView
.SetVisArea( aTmp
);
136 ShellMoveCursor
aTmp( this, bSelect
);
137 return SwCursorShell::Right( nCount
, nMode
, bVisual
);
141 bool SwWrtShell::Up( bool bSelect
, sal_uInt16 nCount
, bool bBasicCall
)
143 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
145 Point
aTmp( VisArea().Pos() );
146 aTmp
.AdjustY( -(VisArea().Height() * nReadOnlyScrollOfst
/ 100) );
147 m_rView
.SetVisArea( aTmp
);
151 ShellMoveCursor
aTmp( this, bSelect
);
152 return SwCursorShell::Up(nCount
);
155 bool SwWrtShell::Down( bool bSelect
, sal_uInt16 nCount
, bool bBasicCall
)
157 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
159 Point
aTmp( VisArea().Pos() );
160 aTmp
.AdjustY(VisArea().Height() * nReadOnlyScrollOfst
/ 100 );
161 aTmp
.setY( m_rView
.SetVScrollMax( aTmp
.Y() ) );
162 m_rView
.SetVisArea( aTmp
);
166 ShellMoveCursor
aTmp( this, bSelect
);
167 return SwCursorShell::Down(nCount
);
170 bool SwWrtShell::LeftMargin( bool bSelect
, bool bBasicCall
)
172 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() )
174 Point
aTmp( VisArea().Pos() );
175 aTmp
.setX( DOCUMENTBORDER
);
176 m_rView
.SetVisArea( aTmp
);
181 ShellMoveCursor
aTmp( this, bSelect
);
182 return SwCursorShell::LeftMargin();
186 bool SwWrtShell::RightMargin( bool bSelect
, bool bBasicCall
)
188 if ( !bSelect
&& !bBasicCall
&& IsCursorReadonly() )
190 Point
aTmp( VisArea().Pos() );
191 aTmp
.setX( GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER
);
192 if( DOCUMENTBORDER
> aTmp
.X() )
193 aTmp
.setX( DOCUMENTBORDER
);
194 m_rView
.SetVisArea( aTmp
);
199 ShellMoveCursor
aTmp( this, bSelect
);
200 return SwCursorShell::RightMargin(bBasicCall
);
204 bool SwWrtShell::GoStart( bool bKeepArea
, bool *pMoveTable
,
205 bool bSelect
, bool bDontMoveRegion
)
207 if ( IsCursorInTable() )
209 const bool bBoxSelection
= HasBoxSelection();
218 if ( !bBoxSelection
&& (MoveSection( GoCurrSection
, fnSectionStart
)
225 if( MoveTable( GotoCurrTable
, fnTableStart
) || bDontMoveRegion
)
231 else if( bBoxSelection
&& pMoveTable
)
233 // JP 09.01.96: We have a box selection (or an empty cell)
234 // and we want select (pMoveTable will be
235 // set in SelAll). Then the table must not
236 // be left, otherwise there is no selection
237 // of the entire table possible!
250 const FrameTypeFlags nFrameType
= GetFrameType(nullptr,false);
251 if ( FrameTypeFlags::FLY_ANY
& nFrameType
)
253 if( MoveSection( GoCurrSection
, fnSectionStart
) )
255 else if ( FrameTypeFlags::FLY_FREE
& nFrameType
|| bDontMoveRegion
)
258 if(( FrameTypeFlags::HEADER
| FrameTypeFlags::FOOTER
| FrameTypeFlags::FOOTNOTE
) & nFrameType
)
260 if ( MoveSection( GoCurrSection
, fnSectionStart
) )
262 else if ( bKeepArea
)
266 return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip
, fnRegionStart
) ||
267 SwCursorShell::SttEndDoc(true);
270 bool SwWrtShell::GoEnd(bool bKeepArea
, const bool *pMoveTable
)
272 if ( pMoveTable
&& *pMoveTable
)
273 return MoveTable( GotoCurrTable
, fnTableEnd
);
275 if ( IsCursorInTable() )
277 if ( MoveSection( GoCurrSection
, fnSectionEnd
) ||
278 MoveTable( GotoCurrTable
, fnTableEnd
) )
283 const FrameTypeFlags nFrameType
= GetFrameType(nullptr,false);
284 if ( FrameTypeFlags::FLY_ANY
& nFrameType
)
286 if ( MoveSection( GoCurrSection
, fnSectionEnd
) )
288 else if ( FrameTypeFlags::FLY_FREE
& nFrameType
)
291 if(( FrameTypeFlags::HEADER
| FrameTypeFlags::FOOTER
| FrameTypeFlags::FOOTNOTE
) & nFrameType
)
293 if ( MoveSection( GoCurrSection
, fnSectionEnd
) )
295 else if ( bKeepArea
)
300 return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip
, fnRegionEnd
) ||
301 SwCursorShell::SttEndDoc(false);
304 bool SwWrtShell::StartOfSection(bool const bSelect
)
306 ShellMoveCursor
aTmp( this, bSelect
);
307 return GoStart(false, nullptr, bSelect
);
310 bool SwWrtShell::EndOfSection(bool const bSelect
)
312 ShellMoveCursor
aTmp( this, bSelect
);
316 bool SwWrtShell::SttNxtPg( bool bSelect
)
318 ShellMoveCursor
aTmp( this, bSelect
);
319 return MovePage( GetNextFrame
, GetFirstSub
);
322 void SwWrtShell::SttPrvPg( bool bSelect
)
324 ShellMoveCursor
aTmp( this, bSelect
);
325 MovePage( GetPrevFrame
, GetFirstSub
);
328 void SwWrtShell::EndNxtPg( bool bSelect
)
330 ShellMoveCursor
aTmp( this, bSelect
);
331 MovePage( GetNextFrame
, GetLastSub
);
334 bool SwWrtShell::EndPrvPg( bool bSelect
)
336 ShellMoveCursor
aTmp( this, bSelect
);
337 return MovePage( GetPrevFrame
, GetLastSub
);
340 bool SwWrtShell::SttPg( bool bSelect
)
342 ShellMoveCursor
aTmp( this, bSelect
);
343 return MovePage( GetThisFrame
, GetFirstSub
);
346 bool SwWrtShell::EndPg( bool bSelect
)
348 ShellMoveCursor
aTmp( this, bSelect
);
349 return MovePage( GetThisFrame
, GetLastSub
);
352 bool SwWrtShell::SttPara( bool bSelect
)
354 ShellMoveCursor
aTmp( this, bSelect
);
355 return MovePara( GoCurrPara
, fnParaStart
);
358 void SwWrtShell::EndPara( bool bSelect
)
360 ShellMoveCursor
aTmp( this, bSelect
);
361 MovePara(GoCurrPara
,fnParaEnd
);
364 // Column-by-jumping.
365 // SSelection with or without
366 // returns success or failure
368 void SwWrtShell::StartOfColumn()
370 ShellMoveCursor
aTmp( this, false/*bSelect*/);
371 MoveColumn(GetCurrColumn
, GetColumnStt
);
374 void SwWrtShell::EndOfColumn()
376 ShellMoveCursor
aTmp( this, false/*bSelect*/);
377 MoveColumn(GetCurrColumn
, GetColumnEnd
);
380 void SwWrtShell::StartOfNextColumn()
382 ShellMoveCursor
aTmp( this, false/*bSelect*/);
383 MoveColumn( GetNextColumn
, GetColumnStt
);
386 void SwWrtShell::EndOfNextColumn()
388 ShellMoveCursor
aTmp( this, false/*bSelect*/);
389 MoveColumn(GetNextColumn
, GetColumnEnd
);
392 void SwWrtShell::StartOfPrevColumn()
394 ShellMoveCursor
aTmp( this, false/*bSelect*/);
395 MoveColumn(GetPrevColumn
, GetColumnStt
);
398 void SwWrtShell::EndOfPrevColumn()
400 ShellMoveCursor
aTmp( this, false/*bSelect*/);
401 MoveColumn(GetPrevColumn
, GetColumnEnd
);
404 bool SwWrtShell::PushCursor(SwTwips lOffset
, bool bSelect
)
407 SwRect
aOldRect( GetCharRect() ), aTmpArea( VisArea() );
409 // m_bDestOnStack indicates if I could not set the coursor at the current
410 // position, because in this region is no content.
411 if( !m_bDestOnStack
)
413 Point
aPt( aOldRect
.Center() );
415 if( !IsCursorVisible() )
416 // set CursorPos to top-/bottom left pos. So the pagescroll is not
417 // be dependent on the current cursor, but on the visarea.
418 aPt
.setY( aTmpArea
.Top() + aTmpArea
.Height() / 2 );
420 aPt
.AdjustY(lOffset
);
421 m_aDest
= GetContentPos(aPt
,lOffset
> 0);
422 m_aDest
.setX( aPt
.X() );
423 m_bDestOnStack
= true;
426 // If we had a frame selection, it must be removed after the m_fnSetCursor
427 // and we have to remember the position on the stack to return to it later.
428 bool bIsFrameSel
= false;
430 //Target position is now within the viewable region -->
431 //Place the cursor at the target position; remember that no target
432 //position is longer on the stack.
433 //The new visible region is to be determined beforehand.
434 aTmpArea
.Pos().AdjustY(lOffset
);
435 if( aTmpArea
.IsInside(m_aDest
) )
442 bIsFrameSel
= IsFrameSelected();
443 bool bIsObjSel
= 0 != IsObjSelected();
446 if( bIsFrameSel
|| bIsObjSel
)
452 GetView().SetDrawFuncPtr( nullptr );
453 GetView().LeaveDrawCreate();
459 (this->*m_fnSetCursor
)( &m_aDest
, true );
461 bDiff
= aOldRect
!= GetCharRect();
465 // In frames take only the upper corner
466 // so that it can be re-selected.
467 aOldRect
.SSize( 5, 5 );
470 // reset Dest. SPoint Flags
471 m_bDestOnStack
= false;
474 // Position into the stack; bDiff indicates if there is a
475 // difference between the old and the new cursor position.
476 m_pCursorStack
.reset( new CursorStack( bDiff
, bIsFrameSel
, aOldRect
.Center(),
477 lOffset
, std::move(m_pCursorStack
) ) );
478 return !m_bDestOnStack
&& bDiff
;
481 bool SwWrtShell::PopCursor(bool bUpdate
, bool bSelect
)
483 if( nullptr == m_pCursorStack
)
486 const bool bValidPos
= m_pCursorStack
->bValidCurPos
;
487 if( bUpdate
&& bValidPos
)
489 // If a predecessor is on the stack,
490 // use the flag for a valid position.
491 SwRect
aTmpArea(VisArea());
492 aTmpArea
.Pos().AdjustY( -(m_pCursorStack
->lOffset
) );
493 if( aTmpArea
.IsInside( m_pCursorStack
->aDocPos
) )
500 (this->*m_fnSetCursor
)(&m_pCursorStack
->aDocPos
, !m_pCursorStack
->bIsFrameSel
);
501 if( m_pCursorStack
->bIsFrameSel
&& IsObjSelectable(m_pCursorStack
->aDocPos
))
504 SelectObj( m_pCursorStack
->aDocPos
);
505 EnterSelFrameMode( &m_pCursorStack
->aDocPos
);
508 // If a discrepancy between the visible range and the
509 // remembered cursor position occurs, all of the remembered
510 // positions are thrown away.
517 m_pCursorStack
= std::move(m_pCursorStack
->pNext
);
518 if( nullptr == m_pCursorStack
)
521 m_bDestOnStack
= false;
526 // Reset of all pushed cursor positions; these will
527 // not be displayed ( --> No Start-/EndAction!!)
529 void SwWrtShell::ResetCursorStack_()
531 while(m_pCursorStack
)
532 m_pCursorStack
= std::move(m_pCursorStack
->pNext
);
534 m_bDestOnStack
= false;
537 if no stack exists --> cancel selection
538 if stack && change of direction
539 --> pop cursor and return
545 bool SwWrtShell::PageCursor(SwTwips lOffset
, bool bSelect
)
547 // Do nothing if an offset of 0 was indicated
548 if(!lOffset
) return false;
549 // Was once used to force a reformat of the layout.
550 // This has not work that way, because the cursor was not set
551 // because this does not happen within a
552 // Start-/EndActionParentheses.
553 // Because only SwViewShell::EndAction() is called at the end,
554 // no updating of the display of the cursor position takes place.
555 // The CursorShell-Actionparentheses cannot be used, because it
556 // always leads to displaying the cursor, thus also,
557 // if after the scroll scrolled in a region without a valid position.
558 // SwViewShell::StartAction();
559 PageMove eDir
= lOffset
> 0? MV_PAGE_DOWN
: MV_PAGE_UP
;
560 // Change of direction and stack present
561 if( eDir
!= m_ePageMove
&& m_ePageMove
!= MV_NO
&& PopCursor( true, bSelect
))
564 const bool bRet
= PushCursor(lOffset
, bSelect
);
569 bool SwWrtShell::GotoPage(sal_uInt16 nPage
, bool bRecord
)
571 ShellMoveCursor
aTmp( this, false);
572 if( SwCursorShell::GotoPage(nPage
) && bRecord
)
584 bool SwWrtShell::GotoMark( const ::sw::mark::IMark
* const pMark
, bool bSelect
)
586 ShellMoveCursor
aTmp( this, bSelect
);
587 SwPosition aPos
= *GetCursor()->GetPoint();
588 bool bRet
= SwCursorShell::GotoMark( pMark
, true/*bStart*/ );
590 m_aNavigationMgr
.addEntry(aPos
);
594 bool SwWrtShell::GotoFly( const OUString
& rName
, FlyCntType eType
, bool bSelFrame
)
596 SwPosition aPos
= *GetCursor()->GetPoint();
597 bool bRet
= SwFEShell::GotoFly(rName
, eType
, bSelFrame
);
599 m_aNavigationMgr
.addEntry(aPos
);
603 bool SwWrtShell::GotoINetAttr( const SwTextINetFormat
& rAttr
)
605 SwPosition aPos
= *GetCursor()->GetPoint();
606 bool bRet
= SwCursorShell::GotoINetAttr(rAttr
);
608 m_aNavigationMgr
.addEntry(aPos
);
612 void SwWrtShell::GotoOutline( SwOutlineNodes::size_type nIdx
)
614 addCurrentPosition();
615 SwCursorShell::GotoOutline (nIdx
);
618 bool SwWrtShell::GotoOutline( const OUString
& rName
)
620 SwPosition aPos
= *GetCursor()->GetPoint();
621 bool bRet
= SwCursorShell::GotoOutline (rName
);
623 m_aNavigationMgr
.addEntry(aPos
);
627 bool SwWrtShell::GotoRegion( const OUString
& rName
)
629 SwPosition aPos
= *GetCursor()->GetPoint();
630 bool bRet
= SwCursorShell::GotoRegion (rName
);
632 m_aNavigationMgr
.addEntry(aPos
);
636 bool SwWrtShell::GotoRefMark( const OUString
& rRefMark
, sal_uInt16 nSubType
,
639 SwPosition aPos
= *GetCursor()->GetPoint();
640 bool bRet
= SwCursorShell::GotoRefMark(rRefMark
, nSubType
, nSeqNo
);
642 m_aNavigationMgr
.addEntry(aPos
);
646 bool SwWrtShell::GotoNextTOXBase( const OUString
* pName
)
648 SwPosition aPos
= *GetCursor()->GetPoint();
649 bool bRet
= SwCursorShell::GotoNextTOXBase(pName
);
651 m_aNavigationMgr
.addEntry(aPos
);
655 bool SwWrtShell::GotoTable( const OUString
& rName
)
657 SwPosition aPos
= *GetCursor()->GetPoint();
658 bool bRet
= SwCursorShell::GotoTable(rName
);
660 m_aNavigationMgr
.addEntry(aPos
);
664 void SwWrtShell::GotoFormatField( const SwFormatField
& rField
) {
665 SwPosition aPos
= *GetCursor()->GetPoint();
666 bool bRet
= SwCursorShell::GotoFormatField(rField
);
668 m_aNavigationMgr
.addEntry(aPos
);
671 const SwRangeRedline
* SwWrtShell::GotoRedline( SwRedlineTable::size_type nArrPos
, bool bSelect
) {
672 SwPosition aPos
= *GetCursor()->GetPoint();
673 const SwRangeRedline
*pRedline
= SwCursorShell::GotoRedline(nArrPos
, bSelect
);
675 m_aNavigationMgr
.addEntry(aPos
);
679 bool SwWrtShell::SelectTextAttr( sal_uInt16 nWhich
, const SwTextAttr
* pAttr
)
683 SwMvContext
aMvContext(this);
685 bRet
= SwCursorShell::SelectTextAttr( nWhich
, false, pAttr
);
691 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */